From adb6986adb1f811d117c35d8872d30a1f2d82c3f Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 7 Apr 2024 20:07:32 +0900 Subject: [PATCH 01/92] docs: add changelog and upgrade for v4.5.1 --- user_guide_src/source/changelogs/index.rst | 1 + user_guide_src/source/changelogs/v4.5.1.rst | 35 ++++++++++++ .../source/installation/upgrade_451.rst | 54 +++++++++++++++++++ .../source/installation/upgrading.rst | 1 + 4 files changed, 91 insertions(+) create mode 100644 user_guide_src/source/changelogs/v4.5.1.rst create mode 100644 user_guide_src/source/installation/upgrade_451.rst diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index 2b8f39479236..8f5c5df8d290 100644 --- a/user_guide_src/source/changelogs/index.rst +++ b/user_guide_src/source/changelogs/index.rst @@ -12,6 +12,7 @@ See all the changes. .. toctree:: :titlesonly: + v4.5.1 v4.5.0 v4.4.8 v4.4.7 diff --git a/user_guide_src/source/changelogs/v4.5.1.rst b/user_guide_src/source/changelogs/v4.5.1.rst new file mode 100644 index 000000000000..9f00193bcf6c --- /dev/null +++ b/user_guide_src/source/changelogs/v4.5.1.rst @@ -0,0 +1,35 @@ +############# +Version 4.5.1 +############# + +Release Date: Unreleased + +**4.5.1 release of CodeIgniter4** + +.. contents:: + :local: + :depth: 3 + +******** +BREAKING +******** + +*************** +Message Changes +*************** + +******* +Changes +******* + +************ +Deprecations +************ + +********** +Bugs Fixed +********** + +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/user_guide_src/source/installation/upgrade_451.rst b/user_guide_src/source/installation/upgrade_451.rst new file mode 100644 index 000000000000..3fc97dc3cffe --- /dev/null +++ b/user_guide_src/source/installation/upgrade_451.rst @@ -0,0 +1,54 @@ +############################# +Upgrading from 4.5.0 to 4.5.1 +############################# + +Please refer to the upgrade instructions corresponding to your installation method. + +- :ref:`Composer Installation App Starter Upgrading ` +- :ref:`Composer Installation Adding CodeIgniter4 to an Existing Project Upgrading ` +- :ref:`Manual Installation Upgrading ` + +.. contents:: + :local: + :depth: 2 + +********************** +Mandatory File Changes +********************** + +**************** +Breaking Changes +**************** + +********************* +Breaking Enhancements +********************* + +************* +Project Files +************* + +Some files in the **project space** (root, app, public, writable) received updates. Due to +these files being outside of the **system** scope they will not be changed without your intervention. + +There are some third-party CodeIgniter modules available to assist with merging changes to +the project space: `Explore on Packagist `_. + +Content Changes +=============== + +The following files received significant changes (including deprecations or visual adjustments) +and it is recommended that you merge the updated versions with your application: + +Config +------ + +- @TODO + +All Changes +=========== + +This is a list of all files in the **project space** that received changes; +many will be simple comments or formatting that have no effect on the runtime: + +- @TODO diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index fb5fecd151a3..9e5e1730daba 100644 --- a/user_guide_src/source/installation/upgrading.rst +++ b/user_guide_src/source/installation/upgrading.rst @@ -16,6 +16,7 @@ See also :doc:`./backward_compatibility_notes`. backward_compatibility_notes + upgrade_451 upgrade_450 upgrade_448 upgrade_447 From 2e0b16ba16ff955626267d218765e5b121dfcaa0 Mon Sep 17 00:00:00 2001 From: Pooya Parsa Dadashi Date: Mon, 8 Apr 2024 03:20:38 +0330 Subject: [PATCH 02/92] docs: fix typo in UG --- user_guide_src/source/installation/upgrade_450.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/installation/upgrade_450.rst b/user_guide_src/source/installation/upgrade_450.rst index 09a6b16d15b1..dd8bae0713b8 100644 --- a/user_guide_src/source/installation/upgrade_450.rst +++ b/user_guide_src/source/installation/upgrade_450.rst @@ -88,7 +88,7 @@ you would get the error response:: 'http_errors' => false, ]); $response->getStatusCode(); // In previous versions: 200 - // In this verrsion: 405 + // In this version: 405 .. _upgrade-450-nested-route-groups-and-options: From 16b8eb8adc5b2d80b8fde744de2f5e8271a5e1cc Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 10:34:16 +0900 Subject: [PATCH 03/92] docs: change comment position Because php-cs-fixer moves the comment line. --- user_guide_src/source/tutorial/static_pages/002.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/user_guide_src/source/tutorial/static_pages/002.php b/user_guide_src/source/tutorial/static_pages/002.php index 9bd046ec3d21..67ed7d951058 100644 --- a/user_guide_src/source/tutorial/static_pages/002.php +++ b/user_guide_src/source/tutorial/static_pages/002.php @@ -2,7 +2,8 @@ namespace App\Controllers; -use CodeIgniter\Exceptions\PageNotFoundException; // Add this line +// Add this line to import the class. +use CodeIgniter\Exceptions\PageNotFoundException; class Pages extends BaseController { From cd16750f71614f5fb09cb92b285c68de9597ab53 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 11:06:51 +0900 Subject: [PATCH 04/92] chore: add .htaccess and index.html for consistency --- .gitignore | 2 +- admin/starter/tests/.htaccess | 6 ++++++ admin/starter/tests/index.html | 11 +++++++++++ writable/debugbar/.gitkeep | 0 writable/debugbar/index.html | 11 +++++++++++ 5 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 admin/starter/tests/.htaccess create mode 100755 admin/starter/tests/index.html delete mode 100755 writable/debugbar/.gitkeep create mode 100755 writable/debugbar/index.html diff --git a/.gitignore b/.gitignore index 71cf213fbfaf..0334b660bb60 100644 --- a/.gitignore +++ b/.gitignore @@ -61,7 +61,7 @@ writable/uploads/* !writable/uploads/index.html writable/debugbar/* -!writable/debugbar/.gitkeep +!writable/debugbar/index.html writable/**/*.db writable/**/*.sqlite diff --git a/admin/starter/tests/.htaccess b/admin/starter/tests/.htaccess new file mode 100755 index 000000000000..3462048add78 --- /dev/null +++ b/admin/starter/tests/.htaccess @@ -0,0 +1,6 @@ + + Require all denied + + + Deny from all + diff --git a/admin/starter/tests/index.html b/admin/starter/tests/index.html new file mode 100755 index 000000000000..b702fbc3967b --- /dev/null +++ b/admin/starter/tests/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + diff --git a/writable/debugbar/.gitkeep b/writable/debugbar/.gitkeep deleted file mode 100755 index e69de29bb2d1..000000000000 diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html new file mode 100755 index 000000000000..b702fbc3967b --- /dev/null +++ b/writable/debugbar/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + From c42df324965ad3477d2bad353a93419e87ec6874 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 11:26:43 +0900 Subject: [PATCH 05/92] docs: fix files in "All Changes" in Project Files --- user_guide_src/source/installation/upgrade_448.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_448.rst b/user_guide_src/source/installation/upgrade_448.rst index 5dd3da148a03..bca6e99af3df 100644 --- a/user_guide_src/source/installation/upgrade_448.rst +++ b/user_guide_src/source/installation/upgrade_448.rst @@ -29,6 +29,5 @@ This is a list of all files in the **project space** that received changes; many will be simple comments or formatting that have no effect on the runtime: - app/.htaccess -- composer.json - public/.htaccess -- tests/.htaccess +- writable/.htaccess From 3020ebb504dfbe502013aaae5d2e594424fb1446 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 12:38:34 +0900 Subject: [PATCH 06/92] docs: update RELEASE.md --- admin/RELEASE.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/admin/RELEASE.md b/admin/RELEASE.md index 37173c4e97b0..8c5f463355fb 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -2,7 +2,7 @@ > Documentation guide based on the releases of `4.0.5` and `4.1.0` on January 31, 2021. > -> Updated for `4.4.3` on October 27, 2023. +> Updated for `4.5.0` on April 7, 2024. > > -MGatner, kenjis @@ -25,10 +25,10 @@ git push upstream HEAD If you release a new minor version. * [ ] Create PR to merge `4.x` into `develop` and merge it -* [ ] Rename the current minor version (e.g., `4.4`) in Setting > Branches > - "Branch protection rules" to the next minor version. E.g. `4.4` → `4.5` +* [ ] Rename the current minor version (e.g., `4.5`) in Setting > Branches > + "Branch protection rules" to the next minor version. E.g. `4.5` → `4.6` * [ ] Delete the merged `4.x` branch (This closes all PRs to the branch) -* [ ] Do the regular release process. Go to the next "Changelog" section +* Do the regular release process. Go to the next "Changelog" section ## Changelog @@ -91,10 +91,11 @@ Work off direct clones of the repos so the release branches persist for a time. * [ ] Update **user_guide_src/source/changelogs/v4.x.x.rst** * Remove the section titles that have no items * [ ] Update **user_guide_src/source/installation/upgrade_{ver}.rst** - * fill in the "All Changes" section, and add it to **upgrading.rst** - * git diff --name-status origin/master -- . ':!system' - * Remove the section titles that have no items - * [Minor version only] Update the "from" version in the title. E.g., `from 4.3.x` → `from 4.3.8` + * [ ] fill in the "All Changes" section, and add it to **upgrading.rst** + * git diff --name-status origin/master -- . ':!system' ':!tests' ':!user_guide_src' + * Note: `tests/` is not used for distribution repos. See `admin/starter/tests/` + * [ ] Remove the section titles that have no items + * [ ] [Minor version only] Update the "from" version in the title. E.g., `from 4.3.x` → `from 4.3.8` * [ ] Run `php admin/prepare-release.php 4.x.x` and push to origin * The above command does the following: * Create a new branch `release-4.x.x` From 9fe63a1a1d6b2b9e080f4461499ad9713715b6ae Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 8 Apr 2024 08:19:45 +0900 Subject: [PATCH 07/92] docs: fix typo in comment --- system/Debug/Toolbar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index c631e4162da4..11df32d2ebb3 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -365,7 +365,7 @@ protected function roundTo(float $number, int $increments = 5): float } /** - * Prepare for debugging.. + * Prepare for debugging. * * @return void */ From b19523e44c3e181170e758ba5aab15c9eb30763e Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 8 Apr 2024 08:20:08 +0900 Subject: [PATCH 08/92] docs: add @var for PhpStorm --- system/Debug/Toolbar.php | 1 + 1 file changed, 1 insertion(+) diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index 11df32d2ebb3..e38cfc27409b 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -378,6 +378,7 @@ public function prepare(?RequestInterface $request = null, ?ResponseInterface $r $app = service('codeigniter'); $request ??= service('request'); + /** @var ResponseInterface $response */ $response ??= service('response'); // Disable the toolbar for downloads From fb2980e50533b51edcb9f85dd7cf77d6e53c67f9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Mon, 8 Apr 2024 08:20:36 +0900 Subject: [PATCH 09/92] fix: TypeError TypeError: str_contains(): Argument #1 ($haystack) must be of type string, null given --- system/Debug/Toolbar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index e38cfc27409b..115016225062 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -434,7 +434,7 @@ public function prepare(?RequestInterface $request = null, ?ResponseInterface $r . $kintScript . PHP_EOL; - if (str_contains($response->getBody(), '')) { + if (str_contains((string) $response->getBody(), '')) { $response->setBody( preg_replace( '//', From 38ffdde4f8ea57966d568d928ede47a591ce7188 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 10:10:14 +0900 Subject: [PATCH 10/92] test: replace empty() --- tests/_support/Config/Registrar.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index 8889021a2d00..d43da3166336 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -134,7 +134,7 @@ public static function Database() // Under GitHub Actions, we can set an ENV var named 'DB' // so that we can test against multiple databases. - if (($group = getenv('DB')) && ! empty(self::$dbConfig[$group])) { + if (($group = getenv('DB')) && isset(self::$dbConfig[$group])) { $config['tests'] = self::$dbConfig[$group]; } From 522cd747ebe3b076adbdf264d1b2cd341b06139d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 10:10:40 +0900 Subject: [PATCH 11/92] test: add types and PHPDoc array types --- tests/_support/Config/Registrar.php | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index d43da3166336..b92c5e24bb16 100644 --- a/tests/_support/Config/Registrar.php +++ b/tests/_support/Config/Registrar.php @@ -23,9 +23,9 @@ class Registrar /** * DB config array for testing purposes. * - * @var array + * @var array|bool|int|string>> */ - protected static $dbConfig = [ + protected static array $dbConfig = [ 'MySQLi' => [ 'DSN' => '', 'hostname' => '127.0.0.1', @@ -126,9 +126,9 @@ class Registrar /** * Override database config * - * @return array + * @return array|bool|int|string> */ - public static function Database() + public static function Database(): array { $config = []; @@ -146,9 +146,9 @@ public static function Database() * * @see PublisherRestrictionsTest::testRegistrarsNotAllowed() * - * @return array + * @return array> */ - public static function Publisher() + public static function Publisher(): array { return [ 'restrictions' => [SUPPORTPATH => '*'], From d3a03a751718222a7dfcfbd0df631af5cdb99cc9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 10:11:12 +0900 Subject: [PATCH 12/92] chore: update phpstan-baseline.php --- phpstan-baseline.php | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index ffe358b48943..44f3fcd4d706 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -10046,26 +10046,6 @@ 'count' => 2, 'path' => __DIR__ . '/tests/_support/Config/Filters.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Config\\\\Registrar\\:\\:Database\\(\\) return type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Config\\\\Registrar\\:\\:Publisher\\(\\) return type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Property Tests\\\\Support\\\\Config\\\\Registrar\\:\\:\\$dbConfig type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Config/Registrar.php', -]; $ignoreErrors[] = [ 'message' => '#^Variable \\$routes might not be defined\\.$#', 'count' => 5, From e1cf987bb828ece2269167272cfd0b50e0d21253 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 11:38:42 +0900 Subject: [PATCH 13/92] fix: TypeError in form() --- system/Helpers/form_helper.php | 2 +- tests/system/Helpers/FormHelperTest.php | 38 ++++++++++++++++--------- 2 files changed, 26 insertions(+), 14 deletions(-) diff --git a/system/Helpers/form_helper.php b/system/Helpers/form_helper.php index 1e3ea4a9152a..2e5b9f7ca576 100644 --- a/system/Helpers/form_helper.php +++ b/system/Helpers/form_helper.php @@ -31,7 +31,7 @@ function form_open(string $action = '', $attributes = [], array $hidden = []): s { // If no action is provided then set to the current url if ($action === '') { - $action = current_url(true); + $action = (string) current_url(true); } // If an action is not a full URL then turn it into one elseif (! str_contains($action, '://')) { // If an action has {locale} diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php index 2ee32da768fc..cfb58c338932 100644 --- a/tests/system/Helpers/FormHelperTest.php +++ b/tests/system/Helpers/FormHelperTest.php @@ -101,21 +101,33 @@ public function testFormOpenWithoutAction(): void { $this->setRequest(); - $before = (new Filters())->globals['before']; - if (in_array('csrf', $before, true) || array_key_exists('csrf', $before)) { - $Value = csrf_hash(); - $Name = csrf_token(); - $expected = << - + $expected = <<<'EOH' +
- EOH; - } else { - $expected = <<<'EOH' - + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $this->assertSame($expected, form_open('', $attributes)); + } - EOH; - } + public function testFormOpenWithoutActionWithCSRF(): void + { + $this->setRequest(); + + // Sets csrf filter. + $filters = config(Filters::class); + $filters->globals['before'][] = 'csrf'; + service('filters')->initialize(); + + $Value = csrf_hash(); + $Name = csrf_token(); + $expected = << + + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', From 2460fafbe8b2f29886177cfca4cbb417e972e58e Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 13:42:00 +0900 Subject: [PATCH 14/92] docs: make PHPDoc types more precise --- phpstan-baseline.php | 5 ----- system/Model.php | 5 +++-- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index ffe358b48943..bd15482a2db5 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -7431,11 +7431,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Model.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Property CodeIgniter\\\\Model\\:\\:\\$tempData type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Model.php', -]; $ignoreErrors[] = [ 'message' => '#^Return type \\(array\\|bool\\|float\\|int\\|object\\|string\\|null\\) of method CodeIgniter\\\\Model\\:\\:__call\\(\\) should be covariant with return type \\(\\$this\\(CodeIgniter\\\\BaseModel\\)\\|null\\) of method CodeIgniter\\\\BaseModel\\:\\:__call\\(\\)$#', 'count' => 1, diff --git a/system/Model.php b/system/Model.php index 61f4350f3117..b3ecfc653943 100644 --- a/system/Model.php +++ b/system/Model.php @@ -40,7 +40,7 @@ * - allow intermingling calls to the builder * - removes the need to use Result object directly in most cases * - * @property BaseConnection $db + * @property-read BaseConnection $db * * @method $this groupBy($by, ?bool $escape = null) * @method $this groupEnd() @@ -123,7 +123,8 @@ class Model extends BaseModel * so that we can capture it (not the builder) * and ensure it gets validated first. * - * @var array + * @var array{escape: array, data: array}|array{} + * @phpstan-var array{escape: array, data: row_array}|array{} */ protected $tempData = []; From edb87e8a45d3a04230502a9cd6baa53e7784559f Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 13:44:03 +0900 Subject: [PATCH 15/92] fix: TypeError when Time is passed to Model --- system/BaseModel.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/system/BaseModel.php b/system/BaseModel.php index 5d08ec59e04c..9b8bb70ed482 100644 --- a/system/BaseModel.php +++ b/system/BaseModel.php @@ -926,6 +926,9 @@ public function insertBatch(?array $set = null, ?bool $escape = null, int $batch $row = (array) $row; } + // Convert any Time instances to appropriate $dateFormat + $row = $this->timeToString($row); + // Validate every row. if (! $this->skipValidation && ! $this->validate($row)) { // Restore $cleanValidationRules @@ -1845,8 +1848,6 @@ protected function transformDataToArray($row, string $type): array $row = $this->converter->toDataSource($row); } elseif ($row instanceof Entity) { $row = $this->converter->extract($row, $onlyChanged); - // Convert any Time instances to appropriate $dateFormat - $row = $this->timeToString($row); } elseif (is_object($row)) { $row = $this->converter->extract($row, $onlyChanged); } @@ -1870,7 +1871,8 @@ protected function transformDataToArray($row, string $type): array throw DataException::forEmptyDataset($type); } - return $row; + // Convert any Time instances to appropriate $dateFormat + return $this->timeToString($row); } /** From 26c9fce62cc3f159d3dae933aae6cdb5e9ee9bd8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 17:02:46 +0900 Subject: [PATCH 16/92] fix: update code because of file changes See https://github.com/codeigniter4/CodeIgniter4/pull/8734 --- system/Commands/Housekeeping/ClearDebugbar.php | 2 +- tests/system/Commands/ClearDebugbarTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Commands/Housekeeping/ClearDebugbar.php b/system/Commands/Housekeeping/ClearDebugbar.php index 2a5c9fa4b536..dd49b24a7656 100644 --- a/system/Commands/Housekeeping/ClearDebugbar.php +++ b/system/Commands/Housekeeping/ClearDebugbar.php @@ -57,7 +57,7 @@ public function run(array $params) { helper('filesystem'); - if (! delete_files(WRITEPATH . 'debugbar')) { + if (! delete_files(WRITEPATH . 'debugbar', false, true)) { // @codeCoverageIgnoreStart CLI::error('Error deleting the debugbar JSON files.'); CLI::newLine(); diff --git a/tests/system/Commands/ClearDebugbarTest.php b/tests/system/Commands/ClearDebugbarTest.php index d55988996ee8..1e86406f7054 100644 --- a/tests/system/Commands/ClearDebugbarTest.php +++ b/tests/system/Commands/ClearDebugbarTest.php @@ -61,7 +61,7 @@ public function testClearDebugbarWorks(): void $result = $this->getStreamFilterBuffer(); $this->assertFileDoesNotExist(WRITEPATH . 'debugbar' . DIRECTORY_SEPARATOR . "debugbar_{$this->time}.json"); - $this->assertFileExists(WRITEPATH . 'debugbar' . DIRECTORY_SEPARATOR . '.gitkeep'); + $this->assertFileExists(WRITEPATH . 'debugbar' . DIRECTORY_SEPARATOR . 'index.html'); $this->assertStringContainsString('Debugbar cleared.', $result); } } From dd85fde438ddb29f99440ab302ce42aa033bd155 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 20:52:12 +0900 Subject: [PATCH 17/92] chore: add writable/index.html --- writable/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100755 writable/index.html diff --git a/writable/index.html b/writable/index.html new file mode 100755 index 000000000000..b702fbc3967b --- /dev/null +++ b/writable/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + From 5e6979b52ae0dc71107ce6166748a1d80618c882 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 10:39:44 +0900 Subject: [PATCH 18/92] fix: Cannot declare class Shield\Config\Auth, because the name is already in use See https://github.com/codeigniter4/shield/issues/1091 --- system/Autoloader/FileLocator.php | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/system/Autoloader/FileLocator.php b/system/Autoloader/FileLocator.php index 97da0fa275eb..14b9a1366ab4 100644 --- a/system/Autoloader/FileLocator.php +++ b/system/Autoloader/FileLocator.php @@ -28,6 +28,13 @@ class FileLocator implements FileLocatorInterface */ protected $autoloader; + /** + * List of classnames that did not exist. + * + * @var list + */ + private array $invalidClassnames = []; + public function __construct(Autoloader $autoloader) { $this->autoloader = $autoloader; @@ -288,14 +295,20 @@ public function findQualifiedNameFromPath(string $path) ), '\\' ); - // Remove the file extension (.php) $className = mb_substr($className, 0, -4); + if (in_array($className, $this->invalidClassnames, true)) { + continue; + } + // Check if this exists if (class_exists($className)) { return $className; } + + // If the class does not exist, it is an invalid classname. + $this->invalidClassnames[] = $className; } } From 5c1d477811f5a08425d2a7a185d9bee06536edcb Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 11:28:07 +0900 Subject: [PATCH 19/92] test: add return void --- .../Models/UserCastsTimestampModel.php | 2 +- .../TranslationNested/TranslationFour.php | 2 +- .../Services/Translation/TranslationOne.php | 2 +- .../Services/Translation/TranslationThree.php | 2 +- .../Services/Translation/TranslationTwo.php | 2 +- .../Autoloader/FileLocatorCachedTest.php | 2 +- ...FactoriesCacheFileVarExportHandlerTest.php | 8 ++-- tests/system/Cache/ResponseCacheTest.php | 12 +++--- tests/system/CodeIgniterTest.php | 4 +- tests/system/Commands/RoutesTest.php | 4 +- .../Commands/Utilities/ConfigCheckTest.php | 4 +- .../Utilities/Routes/FilterFinderTest.php | 4 +- tests/system/CommonFunctionsTest.php | 4 +- tests/system/Config/FactoriesTest.php | 26 ++++++------ .../DataConverter/DataConverterTest.php | 10 ++--- tests/system/Database/Live/ForgeTest.php | 2 +- .../Database/Live/MySQLi/NumberNativeTest.php | 8 ++-- tests/system/Entity/EntityTest.php | 6 +-- tests/system/Filters/FiltersTest.php | 6 +-- .../HTTP/CURLRequestDoNotShareOptionsTest.php | 2 +- tests/system/HTTP/CURLRequestTest.php | 2 +- .../system/HTTP/Files/FileCollectionTest.php | 4 +- tests/system/HTTP/IncomingRequestTest.php | 2 +- .../SiteURIFactoryDetectRoutePathTest.php | 38 +++++++++--------- tests/system/HTTP/SiteURIFactoryTest.php | 8 ++-- tests/system/HTTP/SiteURITest.php | 40 +++++++++---------- tests/system/HTTP/URITest.php | 6 +-- tests/system/Helpers/FormHelperTest.php | 4 +- tests/system/Helpers/HTMLHelperTest.php | 4 +- .../system/Helpers/URLHelper/MiscUrlTest.php | 2 +- .../HotReloader/DirectoryHasherTest.php | 10 ++--- tests/system/I18n/TimeLegacyTest.php | 2 +- tests/system/I18n/TimeTest.php | 2 +- tests/system/Models/WhenWhenNotModelTest.php | 12 +++--- .../system/Router/AutoRouterImprovedTest.php | 26 ++++++------ .../Router/Controllers/Subfolder/Home.php | 2 +- .../Subfolder/Sub/Mycontroller.php | 2 +- .../Router/DefinedRouteCollectorTest.php | 4 +- tests/system/Router/RouteCollectionTest.php | 24 +++++------ tests/system/Security/CheckPhpIniTest.php | 6 +-- tests/system/SuperglobalsTest.php | 2 +- tests/system/Test/ControllerTestTraitTest.php | 2 +- tests/system/Test/FeatureTestTraitTest.php | 8 ++-- .../system/Validation/DotArrayFilterTest.php | 20 +++++----- tests/system/View/ViewTest.php | 2 +- 45 files changed, 173 insertions(+), 173 deletions(-) diff --git a/tests/_support/Models/UserCastsTimestampModel.php b/tests/_support/Models/UserCastsTimestampModel.php index a61bd33472ab..c19353f01319 100644 --- a/tests/_support/Models/UserCastsTimestampModel.php +++ b/tests/_support/Models/UserCastsTimestampModel.php @@ -39,7 +39,7 @@ class UserCastsTimestampModel extends Model protected $useTimestamps = true; protected $dateFormat = 'datetime'; - protected function initialize() + protected function initialize(): void { parent::initialize(); diff --git a/tests/_support/Services/Translation/TranslationNested/TranslationFour.php b/tests/_support/Services/Translation/TranslationNested/TranslationFour.php index 68c41c40c6e7..7b88f93c3df5 100644 --- a/tests/_support/Services/Translation/TranslationNested/TranslationFour.php +++ b/tests/_support/Services/Translation/TranslationNested/TranslationFour.php @@ -15,7 +15,7 @@ class TranslationFour { - public function list() + public function list(): void { lang('TranslationOne.title'); lang('TranslationOne.last_operation_success'); diff --git a/tests/_support/Services/Translation/TranslationOne.php b/tests/_support/Services/Translation/TranslationOne.php index b913700731b5..6f3c222b9dba 100644 --- a/tests/_support/Services/Translation/TranslationOne.php +++ b/tests/_support/Services/Translation/TranslationOne.php @@ -15,7 +15,7 @@ class TranslationOne { - public function list() + public function list(): void { lang('TranslationOne.title'); lang('TranslationOne.DESCRIPTION'); diff --git a/tests/_support/Services/Translation/TranslationThree.php b/tests/_support/Services/Translation/TranslationThree.php index d3ea6c5ec90b..2efc4d40a54f 100644 --- a/tests/_support/Services/Translation/TranslationThree.php +++ b/tests/_support/Services/Translation/TranslationThree.php @@ -15,7 +15,7 @@ class TranslationThree { - public function list() + public function list(): void { lang('TranslationOne.title'); lang('TranslationOne.DESCRIPTION'); diff --git a/tests/_support/Services/Translation/TranslationTwo.php b/tests/_support/Services/Translation/TranslationTwo.php index 8272ec6271a8..b2c0289d28f1 100644 --- a/tests/_support/Services/Translation/TranslationTwo.php +++ b/tests/_support/Services/Translation/TranslationTwo.php @@ -15,7 +15,7 @@ class TranslationTwo { - public function list() + public function list(): void { // Error language keys lang('TranslationTwo'); diff --git a/tests/system/Autoloader/FileLocatorCachedTest.php b/tests/system/Autoloader/FileLocatorCachedTest.php index 675eb50f1899..a10f1f30781b 100644 --- a/tests/system/Autoloader/FileLocatorCachedTest.php +++ b/tests/system/Autoloader/FileLocatorCachedTest.php @@ -74,7 +74,7 @@ protected function tearDown(): void parent::tearDown(); } - public function testDeleteCache() + public function testDeleteCache(): void { $this->assertNotSame([], $this->handler->get('FileLocatorCache')); diff --git a/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php b/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php index ab8fb0f52f56..1566862c2ff9 100644 --- a/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php +++ b/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php @@ -39,14 +39,14 @@ protected function createFactoriesCache(): void $this->cache = new FactoriesCache($this->handler); } - public function testInstantiate() + public function testInstantiate(): void { $this->createFactoriesCache(); $this->assertInstanceOf(FactoriesCache::class, $this->cache); } - public function testSave() + public function testSave(): void { Factories::reset(); Factories::config('App'); @@ -62,7 +62,7 @@ public function testSave() $this->assertArrayHasKey('App', $cachedData['aliases']); } - public function testLoad() + public function testLoad(): void { Factories::reset(); /** @var App $appConfig */ @@ -80,7 +80,7 @@ public function testLoad() $this->assertSame('http://test.example.jp/this-is-test/', $appConfig->baseURL); } - public function testDelete() + public function testDelete(): void { $this->createFactoriesCache(); diff --git a/tests/system/Cache/ResponseCacheTest.php b/tests/system/Cache/ResponseCacheTest.php index fd2363171ec1..059ad7d8f905 100644 --- a/tests/system/Cache/ResponseCacheTest.php +++ b/tests/system/Cache/ResponseCacheTest.php @@ -93,7 +93,7 @@ private function createResponseCache(?CacheConfig $cacheConfig = null): Response return (new ResponseCache($cacheConfig, $cache))->setTtl(300); } - public function testCachePageIncomingRequest() + public function testCachePageIncomingRequest(): void { $pageCache = $this->createResponseCache(); @@ -131,7 +131,7 @@ public function testCachePageIncomingRequest() $this->assertNull($cachedResponse); } - public function testCachePageIncomingRequestWithCacheQueryString() + public function testCachePageIncomingRequestWithCacheQueryString(): void { $cacheConfig = new CacheConfig(); $cacheConfig->cacheQueryString = true; @@ -169,7 +169,7 @@ public function testCachePageIncomingRequestWithCacheQueryString() $this->assertNull($cachedResponse); } - public function testCachePageIncomingRequestWithHttpMethods() + public function testCachePageIncomingRequestWithHttpMethods(): void { $pageCache = $this->createResponseCache(); @@ -189,7 +189,7 @@ public function testCachePageIncomingRequestWithHttpMethods() $this->assertNull($cachedResponse); } - public function testCachePageCLIRequest() + public function testCachePageCLIRequest(): void { $pageCache = $this->createResponseCache(); @@ -217,7 +217,7 @@ public function testCachePageCLIRequest() $this->assertNull($cachedResponse); } - public function testUnserializeError() + public function testUnserializeError(): void { $this->expectException(ErrorException::class); $this->expectExceptionMessage('unserialize(): Error at offset 0 of 12 bytes'); @@ -243,7 +243,7 @@ public function testUnserializeError() $pageCache->get($request, new Response($this->appConfig)); } - public function testInvalidCacheError() + public function testInvalidCacheError(): void { $this->expectException(Exception::class); $this->expectExceptionMessage('Error unserializing page cache'); diff --git a/tests/system/CodeIgniterTest.php b/tests/system/CodeIgniterTest.php index d6e93ab7a6d0..fadfe365307a 100644 --- a/tests/system/CodeIgniterTest.php +++ b/tests/system/CodeIgniterTest.php @@ -83,7 +83,7 @@ public function testRunEmptyDefaultRoute(): void $this->assertStringContainsString('Welcome to CodeIgniter', $output); } - public function testOutputBufferingControl() + public function testOutputBufferingControl(): void { ob_start(); $this->codeigniter->run(); @@ -310,7 +310,7 @@ public function testRunExecuteFilterByClassName(): void $this->resetServices(); } - public function testRegisterSameFilterTwiceWithDifferentArgument() + public function testRegisterSameFilterTwiceWithDifferentArgument(): void { $this->expectException(ConfigException::class); $this->expectExceptionMessage('"test-customfilter" already has arguments: null'); diff --git a/tests/system/Commands/RoutesTest.php b/tests/system/Commands/RoutesTest.php index b6384858f5fb..634078e98409 100644 --- a/tests/system/Commands/RoutesTest.php +++ b/tests/system/Commands/RoutesTest.php @@ -116,7 +116,7 @@ public function testRoutesCommandSortByHandler(): void $this->assertStringContainsString($expected, $this->getBuffer()); } - public function testRoutesCommandHostHostname() + public function testRoutesCommandHostHostname(): void { Services::injectMock('routes', null); @@ -145,7 +145,7 @@ public function testRoutesCommandHostHostname() $this->assertStringContainsString($expected, $this->getBuffer()); } - public function testRoutesCommandHostSubdomain() + public function testRoutesCommandHostSubdomain(): void { Services::injectMock('routes', null); diff --git a/tests/system/Commands/Utilities/ConfigCheckTest.php b/tests/system/Commands/Utilities/ConfigCheckTest.php index 9d2c5fdfd3d3..b7e3890a5e61 100644 --- a/tests/system/Commands/Utilities/ConfigCheckTest.php +++ b/tests/system/Commands/Utilities/ConfigCheckTest.php @@ -72,7 +72,7 @@ public function testCommandConfigCheckNonexistentClass(): void ); } - public function testGetKintD() + public function testGetKintD(): void { $command = new ConfigCheck(Services::logger(), Services::commands()); $getKintD = $this->getPrivateMethodInvoker($command, 'getKintD'); @@ -112,7 +112,7 @@ public function testGetKintD() ); } - public function testGetVarDump() + public function testGetVarDump(): void { $command = new ConfigCheck(Services::logger(), Services::commands()); $getVarDump = $this->getPrivateMethodInvoker($command, 'getVarDump'); diff --git a/tests/system/Commands/Utilities/Routes/FilterFinderTest.php b/tests/system/Commands/Utilities/Routes/FilterFinderTest.php index ad3c638fc42e..495fbb46f31b 100644 --- a/tests/system/Commands/Utilities/Routes/FilterFinderTest.php +++ b/tests/system/Commands/Utilities/Routes/FilterFinderTest.php @@ -190,7 +190,7 @@ public function testFindGlobalsAndRouteMultipleFilters(): void $this->assertSame($expected, $filters); } - public function testFilterOrder() + public function testFilterOrder(): void { $collection = $this->createRouteCollection([]); $collection->get('/', ' Home::index', ['filter' => ['route1', 'route2']]); @@ -252,7 +252,7 @@ public function testFilterOrder() $this->assertSame($expected, $filters); } - public function testFilterOrderWithOldFilterOrder() + public function testFilterOrderWithOldFilterOrder(): void { $feature = config(Feature::class); $feature->oldFilterOrder = true; diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index 35866f640ee9..7e1e9d27c349 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -189,14 +189,14 @@ public function testSolidusElementXHTML(): void $this->enableHtml5(); } - private function disableHtml5() + private function disableHtml5(): void { $doctypes = new DocTypes(); $doctypes->html5 = false; _solidus($doctypes); } - private function enableHtml5() + private function enableHtml5(): void { $doctypes = new DocTypes(); _solidus($doctypes); diff --git a/tests/system/Config/FactoriesTest.php b/tests/system/Config/FactoriesTest.php index f40b0968fb74..4ae2a3f844ad 100644 --- a/tests/system/Config/FactoriesTest.php +++ b/tests/system/Config/FactoriesTest.php @@ -259,7 +259,7 @@ class_alias(SomeWidget::class, $class); $this->assertInstanceOf(SomeWidget::class, $result); } - public function testShortnameReturnsConfigInApp() + public function testShortnameReturnsConfigInApp(): void { // Create a config class in App $file = APPPATH . 'Config/TestRegistrar.php'; @@ -279,7 +279,7 @@ class TestRegistrar unlink($file); } - public function testFullClassnameIgnoresPreferApp() + public function testFullClassnameIgnoresPreferApp(): void { // Create a config class in App $file = APPPATH . 'Config/TestRegistrar.php'; @@ -317,7 +317,7 @@ class_alias(SomeWidget::class, $class); $this->assertInstanceOf(OtherWidget::class, $result); } - public function testCanLoadTwoCellsWithSameShortName() + public function testCanLoadTwoCellsWithSameShortName(): void { $cell1 = Factories::cells('\\' . SampleClass::class); $cell2 = Factories::cells('\\' . \Tests\Support\View\OtherCells\SampleClass::class); @@ -325,7 +325,7 @@ public function testCanLoadTwoCellsWithSameShortName() $this->assertNotSame($cell1, $cell2); } - public function testCanLoadSharedConfigWithDifferentAlias() + public function testCanLoadSharedConfigWithDifferentAlias(): void { $config1 = Factories::config(App::class); $config2 = Factories::config('App'); @@ -333,7 +333,7 @@ public function testCanLoadSharedConfigWithDifferentAlias() $this->assertSame($config1, $config2); } - public function testDefineSameAliasTwiceWithDifferentClasses() + public function testDefineSameAliasTwiceWithDifferentClasses(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( @@ -352,7 +352,7 @@ public function testDefineSameAliasTwiceWithDifferentClasses() ); } - public function testDefineSameAliasAndSameClassTwice() + public function testDefineSameAliasAndSameClassTwice(): void { Factories::define( 'models', @@ -370,7 +370,7 @@ public function testDefineSameAliasAndSameClassTwice() $this->assertInstanceOf(UserModel::class, $model); } - public function testDefineNonExistentClass() + public function testDefineNonExistentClass(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage('No such class: App\Models\UserModel'); @@ -382,7 +382,7 @@ public function testDefineNonExistentClass() ); } - public function testDefineAfterLoading() + public function testDefineAfterLoading(): void { $this->expectException(InvalidArgumentException::class); $this->expectExceptionMessage( @@ -398,7 +398,7 @@ public function testDefineAfterLoading() ); } - public function testDefineAndLoad() + public function testDefineAndLoad(): void { Factories::define( 'models', @@ -447,7 +447,7 @@ public function testSetComponentInstances(array $data) /** * @depends testSetComponentInstances */ - public function testIsUpdated(array $data) + public function testIsUpdated(array $data): void { Factories::reset(); @@ -466,21 +466,21 @@ public function testIsUpdated(array $data) $this->assertFalse(Factories::isUpdated('config')); } - public function testGetReturnsFactoriesConfigInstance() + public function testGetReturnsFactoriesConfigInstance(): void { $config = Factories::config('App'); $this->assertSame($config, Factories::get('config', 'App')); } - public function testGetCreatesConfigInstanceAndFactoriesConfigReturnsIt() + public function testGetCreatesConfigInstanceAndFactoriesConfigReturnsIt(): void { $config = Factories::get('config', 'App'); $this->assertSame($config, Factories::config('App')); } - public function testGetNonexistentClass() + public function testGetNonexistentClass(): void { $config = Factories::get('config', 'NonexistentClass'); diff --git a/tests/system/DataConverter/DataConverterTest.php b/tests/system/DataConverter/DataConverterTest.php index acb31074b3da..e5ae5e7abe90 100644 --- a/tests/system/DataConverter/DataConverterTest.php +++ b/tests/system/DataConverter/DataConverterTest.php @@ -538,7 +538,7 @@ private function createDataConverter( return new DataConverter($types, $handlers, $helper, $reconstructor, $extractor); } - public function testReconstructObjectWithReconstructMethod() + public function testReconstructObjectWithReconstructMethod(): void { $types = [ 'id' => 'int', @@ -565,7 +565,7 @@ public function testReconstructObjectWithReconstructMethod() $this->assertInstanceOf(Time::class, $obj->updated_at); } - public function testReconstructObjectWithClosure() + public function testReconstructObjectWithClosure(): void { $types = [ 'id' => 'int', @@ -598,7 +598,7 @@ public function testReconstructObjectWithClosure() $this->assertInstanceOf(Time::class, $obj->updated_at); } - public function testExtract() + public function testExtract(): void { $types = [ 'id' => 'int', @@ -630,7 +630,7 @@ public function testExtract() ], $array); } - public function testExtractWithExtractMethod() + public function testExtractWithExtractMethod(): void { $types = [ 'id' => 'int', @@ -662,7 +662,7 @@ public function testExtractWithExtractMethod() ], $array); } - public function testExtractWithClosure() + public function testExtractWithClosure(): void { $types = [ 'id' => 'int', diff --git a/tests/system/Database/Live/ForgeTest.php b/tests/system/Database/Live/ForgeTest.php index 44f143301f9d..8061e80d7241 100644 --- a/tests/system/Database/Live/ForgeTest.php +++ b/tests/system/Database/Live/ForgeTest.php @@ -875,7 +875,7 @@ public function testAddColumn(): void $this->assertSame('username', $fieldNames[1]); } - public function testAddColumnNull() + public function testAddColumnNull(): void { $this->forge->dropTable('forge_test_table', true); diff --git a/tests/system/Database/Live/MySQLi/NumberNativeTest.php b/tests/system/Database/Live/MySQLi/NumberNativeTest.php index 81ec7a01fd40..5ba37eaf804e 100644 --- a/tests/system/Database/Live/MySQLi/NumberNativeTest.php +++ b/tests/system/Database/Live/MySQLi/NumberNativeTest.php @@ -40,7 +40,7 @@ protected function setUp(): void $this->tests = $config->tests; } - public function testEnableNumberNative() + public function testEnableNumberNative(): void { $this->tests['numberNative'] = true; @@ -53,7 +53,7 @@ public function testEnableNumberNative() $this->assertTrue($db1->numberNative); } - public function testDisableNumberNative() + public function testDisableNumberNative(): void { $this->tests['numberNative'] = false; @@ -66,7 +66,7 @@ public function testDisableNumberNative() $this->assertFalse($db1->numberNative); } - public function testQueryDataAfterEnableNumberNative() + public function testQueryDataAfterEnableNumberNative(): void { $this->tests['numberNative'] = true; @@ -84,7 +84,7 @@ public function testQueryDataAfterEnableNumberNative() $this->assertIsInt($data->type_integer); } - public function testQueryDataAfterDisableNumberNative() + public function testQueryDataAfterDisableNumberNative(): void { $this->tests['numberNative'] = false; diff --git a/tests/system/Entity/EntityTest.php b/tests/system/Entity/EntityTest.php index 20d846551851..37e65c497e57 100644 --- a/tests/system/Entity/EntityTest.php +++ b/tests/system/Entity/EntityTest.php @@ -36,7 +36,7 @@ final class EntityTest extends CIUnitTestCase { use ReflectionHelper; - public function testSetStringToPropertyNamedAttributes() + public function testSetStringToPropertyNamedAttributes(): void { $entity = $this->getEntity(); @@ -48,7 +48,7 @@ public function testSetStringToPropertyNamedAttributes() /** * @see https://github.com/codeigniter4/CodeIgniter4/issues */ - public function testSetArrayToPropertyNamedAttributes() + public function testSetArrayToPropertyNamedAttributes(): void { $entity = new Entity(); @@ -84,7 +84,7 @@ public function testGetterSetters(): void $this->assertSame('bar:thanks:bar', $entity->bar); } - public function testNewGetterSetters() + public function testNewGetterSetters(): void { $entity = $this->getNewSetterGetterEntity(); diff --git a/tests/system/Filters/FiltersTest.php b/tests/system/Filters/FiltersTest.php index 7905cfefdae6..9ce2c1b28985 100644 --- a/tests/system/Filters/FiltersTest.php +++ b/tests/system/Filters/FiltersTest.php @@ -842,7 +842,7 @@ public function testEnableFilter(): void $this->assertContains('google', $filters['before']); } - public function testFiltersWithArguments() + public function testFiltersWithArguments(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; @@ -876,7 +876,7 @@ public function testFiltersWithArguments() $this->assertSame('admin;super', $response->getBody()); } - public function testFilterWithArgumentsIsDefined() + public function testFilterWithArgumentsIsDefined(): void { $this->expectException(ConfigException::class); $this->expectExceptionMessage('"role" already has arguments: admin,super'); @@ -901,7 +901,7 @@ public function testFilterWithArgumentsIsDefined() $filters->initialize('admin/user/bar'); } - public function testFilterWithoutArgumentsIsDefined() + public function testFilterWithoutArgumentsIsDefined(): void { $_SERVER['REQUEST_METHOD'] = 'GET'; diff --git a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php index f6e06a882191..1adea4d7d106 100644 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php @@ -562,7 +562,7 @@ public function testSSLWithBadKey(): void ]); } - public function testProxyuOption() + public function testProxyuOption(): void { $this->request->request('get', 'http://example.com', [ 'proxy' => 'http://localhost:3128', diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 6b51b4d585f4..7bcabaf3f986 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -560,7 +560,7 @@ public function testSSLWithBadKey(): void ]); } - public function testProxyuOption() + public function testProxyuOption(): void { $this->request->request('get', 'http://example.com', [ 'proxy' => 'http://localhost:3128', diff --git a/tests/system/HTTP/Files/FileCollectionTest.php b/tests/system/HTTP/Files/FileCollectionTest.php index d2bd760b0cab..3b565156aa6b 100644 --- a/tests/system/HTTP/Files/FileCollectionTest.php +++ b/tests/system/HTTP/Files/FileCollectionTest.php @@ -455,7 +455,7 @@ public function testErrorWithNoError(): void $this->assertSame(UPLOAD_ERR_OK, $file->getError()); } - public function testClientPathReturnsValidFullPath() + public function testClientPathReturnsValidFullPath(): void { $_FILES = [ 'userfile' => [ @@ -473,7 +473,7 @@ public function testClientPathReturnsValidFullPath() $this->assertSame('someDir/someFile.txt', $file->getClientPath()); } - public function testClientPathReturnsNullWhenFullPathIsNull() + public function testClientPathReturnsNullWhenFullPathIsNull(): void { $_FILES = [ 'userfile' => [ diff --git a/tests/system/HTTP/IncomingRequestTest.php b/tests/system/HTTP/IncomingRequestTest.php index 7060af62f31f..e0d827523405 100644 --- a/tests/system/HTTP/IncomingRequestTest.php +++ b/tests/system/HTTP/IncomingRequestTest.php @@ -223,7 +223,7 @@ public function testSetBadLocale(): void $this->assertSame('es', $request->getLocale()); } - public function testSetValidLocales() + public function testSetValidLocales(): void { $config = new App(); $config->supportedLocales = ['en', 'es']; diff --git a/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php b/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php index b5f1b4d1099d..f6386b858165 100644 --- a/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php +++ b/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php @@ -43,7 +43,7 @@ private function createSiteURIFactory(array $server, ?App $appConfig = null): Si return new SiteURIFactory($appConfig, $superglobals); } - public function testDefault() + public function testDefault(): void { // /index.php/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php/woot'; @@ -55,7 +55,7 @@ public function testDefault() $this->assertSame($expected, $factory->detectRoutePath()); } - public function testDefaultEmpty() + public function testDefaultEmpty(): void { // / $_SERVER['REQUEST_URI'] = '/'; @@ -67,7 +67,7 @@ public function testDefaultEmpty() $this->assertSame($expected, $factory->detectRoutePath()); } - public function testRequestURI() + public function testRequestURI(): void { // /index.php/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php/woot'; @@ -79,7 +79,7 @@ public function testRequestURI() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURINested() + public function testRequestURINested(): void { // I'm not sure but this is a case of Apache config making such SERVER // values? @@ -99,7 +99,7 @@ public function testRequestURINested() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURISubfolder() + public function testRequestURISubfolder(): void { // /ci/index.php/popcorn/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/ci/index.php/popcorn/woot'; @@ -111,7 +111,7 @@ public function testRequestURISubfolder() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURINoIndex() + public function testRequestURINoIndex(): void { // /sub/example $_SERVER['REQUEST_URI'] = '/sub/example'; @@ -123,7 +123,7 @@ public function testRequestURINoIndex() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURINginx() + public function testRequestURINginx(): void { // /ci/index.php/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php/woot?code=good'; @@ -135,7 +135,7 @@ public function testRequestURINginx() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURINginxRedirecting() + public function testRequestURINginxRedirecting(): void { // /?/ci/index.php/woot $_SERVER['REQUEST_URI'] = '/?/ci/woot'; @@ -147,7 +147,7 @@ public function testRequestURINginxRedirecting() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURISuppressed() + public function testRequestURISuppressed(): void { // /woot?code=good#pos $_SERVER['REQUEST_URI'] = '/woot'; @@ -159,7 +159,7 @@ public function testRequestURISuppressed() $this->assertSame($expected, $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURIGetPath() + public function testRequestURIGetPath(): void { // /index.php/fruits/banana $_SERVER['REQUEST_URI'] = '/index.php/fruits/banana'; @@ -170,7 +170,7 @@ public function testRequestURIGetPath() $this->assertSame('fruits/banana', $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURIPathIsRelative() + public function testRequestURIPathIsRelative(): void { // /sub/folder/index.php/fruits/banana $_SERVER['REQUEST_URI'] = '/sub/folder/index.php/fruits/banana'; @@ -181,7 +181,7 @@ public function testRequestURIPathIsRelative() $this->assertSame('fruits/banana', $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURIStoresDetectedPath() + public function testRequestURIStoresDetectedPath(): void { // /fruits/banana $_SERVER['REQUEST_URI'] = '/fruits/banana'; @@ -194,7 +194,7 @@ public function testRequestURIStoresDetectedPath() $this->assertSame('fruits/banana', $factory->detectRoutePath('REQUEST_URI')); } - public function testRequestURIPathIsNeverRediscovered() + public function testRequestURIPathIsNeverRediscovered(): void { $_SERVER['REQUEST_URI'] = '/fruits/banana'; $_SERVER['SCRIPT_NAME'] = '/index.php'; @@ -207,7 +207,7 @@ public function testRequestURIPathIsNeverRediscovered() $this->assertSame('fruits/banana', $factory->detectRoutePath('REQUEST_URI')); } - public function testQueryString() + public function testQueryString(): void { // /index.php?/ci/woot $_SERVER['REQUEST_URI'] = '/index.php?/ci/woot'; @@ -222,7 +222,7 @@ public function testQueryString() $this->assertSame($expected, $factory->detectRoutePath('QUERY_STRING')); } - public function testQueryStringWithQueryString() + public function testQueryStringWithQueryString(): void { // /index.php?/ci/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php?/ci/woot?code=good'; @@ -239,7 +239,7 @@ public function testQueryStringWithQueryString() $this->assertSame(['code' => 'good'], $_GET); } - public function testQueryStringEmpty() + public function testQueryStringEmpty(): void { // /index.php? $_SERVER['REQUEST_URI'] = '/index.php?'; @@ -251,7 +251,7 @@ public function testQueryStringEmpty() $this->assertSame($expected, $factory->detectRoutePath('QUERY_STRING')); } - public function testPathInfoUnset() + public function testPathInfoUnset(): void { // /index.php/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php/woot'; @@ -263,7 +263,7 @@ public function testPathInfoUnset() $this->assertSame($expected, $factory->detectRoutePath('PATH_INFO')); } - public function testPathInfoSubfolder() + public function testPathInfoSubfolder(): void { $appConfig = new App(); $appConfig->baseURL = 'http://localhost:8888/ci431/public/'; @@ -285,7 +285,7 @@ public function testPathInfoSubfolder() * @param string $path * @param string $detectPath */ - public function testExtensionPHP($path, $detectPath) + public function testExtensionPHP($path, $detectPath): void { $config = new App(); $config->baseURL = 'http://example.com/'; diff --git a/tests/system/HTTP/SiteURIFactoryTest.php b/tests/system/HTTP/SiteURIFactoryTest.php index 594ce63d08ec..9b0a55d20b5f 100644 --- a/tests/system/HTTP/SiteURIFactoryTest.php +++ b/tests/system/HTTP/SiteURIFactoryTest.php @@ -41,7 +41,7 @@ private function createSiteURIFactory(?App $config = null, ?Superglobals $superg return new SiteURIFactory($config, $superglobals); } - public function testCreateFromGlobals() + public function testCreateFromGlobals(): void { // http://localhost:8080/index.php/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php/woot?code=good'; @@ -62,7 +62,7 @@ public function testCreateFromGlobals() $this->assertSame('woot', $uri->getRoutePath()); } - public function testCreateFromGlobalsAllowedHost() + public function testCreateFromGlobalsAllowedHost(): void { // http://users.example.jp/index.php/woot?code=good#pos $_SERVER['REQUEST_URI'] = '/index.php/woot?code=good'; @@ -95,7 +95,7 @@ public function testCreateFromStringWithIndexPage( string $expectUriString, string $expectedPath, string $expectedRoutePath - ) { + ): void { $factory = $this->createSiteURIFactory(); $uri = $factory->createFromString($uriString); @@ -138,7 +138,7 @@ public function testCreateFromStringWithoutIndexPage( string $expectUriString, string $expectedPath, string $expectedRoutePath - ) { + ): void { $config = new App(); $config->indexPage = ''; $factory = $this->createSiteURIFactory($config); diff --git a/tests/system/HTTP/SiteURITest.php b/tests/system/HTTP/SiteURITest.php index 26a3102e1fea..80deeddc2879 100644 --- a/tests/system/HTTP/SiteURITest.php +++ b/tests/system/HTTP/SiteURITest.php @@ -42,7 +42,7 @@ public function testConstructor( string $expectedFragment, array $expectedSegments, int $expectedTotalSegments - ) { + ): void { $config = new App(); $config->indexPage = $indexPage; $config->baseURL = $baseURL; @@ -270,7 +270,7 @@ public static function provideRelativePathWithQueryOrFragment(): iterable ]; } - public function testConstructorHost() + public function testConstructorHost(): void { $config = new App(); $config->allowedHostnames = ['sub.example.com']; @@ -284,7 +284,7 @@ public function testConstructorHost() $this->assertSame('http://sub.example.com/', $uri->getBaseURL()); } - public function testConstructorScheme() + public function testConstructorScheme(): void { $config = new App(); @@ -295,7 +295,7 @@ public function testConstructorScheme() $this->assertSame('https://example.com/', $uri->getBaseURL()); } - public function testConstructorEmptyScheme() + public function testConstructorEmptyScheme(): void { $config = new App(); @@ -306,7 +306,7 @@ public function testConstructorEmptyScheme() $this->assertSame('http://example.com/', $uri->getBaseURL()); } - public function testConstructorForceGlobalSecureRequests() + public function testConstructorForceGlobalSecureRequests(): void { $config = new App(); $config->forceGlobalSecureRequests = true; @@ -317,7 +317,7 @@ public function testConstructorForceGlobalSecureRequests() $this->assertSame('https://example.com/', $uri->getBaseURL()); } - public function testConstructorInvalidBaseURL() + public function testConstructorInvalidBaseURL(): void { $this->expectException(ConfigException::class); @@ -341,7 +341,7 @@ public function testSetPath( string $expectedFragment, array $expectedSegments, int $expectedTotalSegments - ) { + ): void { $config = new App(); $config->indexPage = $indexPage; $config->baseURL = $baseURL; @@ -361,7 +361,7 @@ public function testSetPath( $this->assertSame($expectedTotalSegments, $uri->getTotalSegments()); } - public function testSetSegment() + public function testSetSegment(): void { $config = new App(); @@ -378,7 +378,7 @@ public function testSetSegment() $this->assertSame(2, $uri->getTotalSegments()); } - public function testSetSegmentOutOfRange() + public function testSetSegmentOutOfRange(): void { $this->expectException(HTTPException::class); @@ -389,7 +389,7 @@ public function testSetSegmentOutOfRange() $uri->setSegment(4, 'four'); } - public function testSetSegmentSilentOutOfRange() + public function testSetSegmentSilentOutOfRange(): void { $config = new App(); $uri = new SiteURI($config); @@ -400,7 +400,7 @@ public function testSetSegmentSilentOutOfRange() $this->assertSame(['one', 'method'], $uri->getSegments()); } - public function testSetSegmentZero() + public function testSetSegmentZero(): void { $this->expectException(HTTPException::class); @@ -411,7 +411,7 @@ public function testSetSegmentZero() $uri->setSegment(0, 'four'); } - public function testSetSegmentSubfolder() + public function testSetSegmentSubfolder(): void { $config = new App(); $config->baseURL = 'http://example.com/ci4/'; @@ -429,7 +429,7 @@ public function testSetSegmentSubfolder() $this->assertSame(2, $uri->getTotalSegments()); } - public function testGetRoutePath() + public function testGetRoutePath(): void { $config = new App(); $uri = new SiteURI($config); @@ -437,7 +437,7 @@ public function testGetRoutePath() $this->assertSame('', $uri->getRoutePath()); } - public function testGetSegments() + public function testGetSegments(): void { $config = new App(); $uri = new SiteURI($config); @@ -445,7 +445,7 @@ public function testGetSegments() $this->assertSame([], $uri->getSegments()); } - public function testGetSegmentZero() + public function testGetSegmentZero(): void { $this->expectException(HTTPException::class); @@ -456,7 +456,7 @@ public function testGetSegmentZero() $uri->getSegment(0); } - public function testGetSegmentOutOfRange() + public function testGetSegmentOutOfRange(): void { $this->expectException(HTTPException::class); @@ -467,7 +467,7 @@ public function testGetSegmentOutOfRange() $uri->getSegment(4); } - public function testGetTotalSegments() + public function testGetTotalSegments(): void { $config = new App(); $uri = new SiteURI($config); @@ -475,7 +475,7 @@ public function testGetTotalSegments() $this->assertSame(0, $uri->getTotalSegments()); } - public function testSetURI() + public function testSetURI(): void { $this->expectException(BadMethodCallException::class); @@ -485,7 +485,7 @@ public function testSetURI() $uri->setURI('http://another.site.example.jp/'); } - public function testSetBaseURI() + public function testSetBaseURI(): void { $this->expectException(BadMethodCallException::class); @@ -495,7 +495,7 @@ public function testSetBaseURI() $uri->setBaseURL('http://another.site.example.jp/'); } - public function testGetBaseURL() + public function testGetBaseURL(): void { $config = new App(); $uri = new SiteURI($config); diff --git a/tests/system/HTTP/URITest.php b/tests/system/HTTP/URITest.php index 41780ebb7ec4..0211d6d2e1f9 100644 --- a/tests/system/HTTP/URITest.php +++ b/tests/system/HTTP/URITest.php @@ -242,7 +242,7 @@ public function testSetSchemeSetsValue(): void $this->assertSame($expected, (string) $uri); } - public function testWithScheme() + public function testWithScheme(): void { $url = 'example.com'; $uri = new URI('http://' . $url); @@ -253,7 +253,7 @@ public function testWithScheme() $this->assertSame('http://' . $url, (string) $uri); } - public function testWithSchemeSetsHttps() + public function testWithSchemeSetsHttps(): void { $url = 'http://example.com/path'; $uri = new URI($url); @@ -269,7 +269,7 @@ public function testWithSchemeSetsHttps() $this->assertSame($expected, (string) $uri); } - public function testWithSchemeSetsEmpty() + public function testWithSchemeSetsEmpty(): void { $url = 'example.com'; $uri = new URI('http://' . $url); diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php index cfb58c338932..26e9c97fbcfd 100644 --- a/tests/system/Helpers/FormHelperTest.php +++ b/tests/system/Helpers/FormHelperTest.php @@ -299,14 +299,14 @@ public function testFormInputXHTML(): void $this->enableHtml5(); } - private function disableHtml5() + private function disableHtml5(): void { $doctypes = new DocTypes(); $doctypes->html5 = false; _solidus($doctypes); } - private function enableHtml5() + private function enableHtml5(): void { $doctypes = new DocTypes(); _solidus($doctypes); diff --git a/tests/system/Helpers/HTMLHelperTest.php b/tests/system/Helpers/HTMLHelperTest.php index 0fc05a77ea91..ecce00af6783 100755 --- a/tests/system/Helpers/HTMLHelperTest.php +++ b/tests/system/Helpers/HTMLHelperTest.php @@ -218,14 +218,14 @@ public function testIMGXHTML(): void $this->enableHtml5(); } - private function disableHtml5() + private function disableHtml5(): void { $doctypes = new DocTypes(); $doctypes->html5 = false; _solidus($doctypes); } - private function enableHtml5() + private function enableHtml5(): void { $doctypes = new DocTypes(); _solidus($doctypes); diff --git a/tests/system/Helpers/URLHelper/MiscUrlTest.php b/tests/system/Helpers/URLHelper/MiscUrlTest.php index 6670b9fec4d2..1a15bb4c1fac 100644 --- a/tests/system/Helpers/URLHelper/MiscUrlTest.php +++ b/tests/system/Helpers/URLHelper/MiscUrlTest.php @@ -940,7 +940,7 @@ public function testUrlToWithNamedRouteWithNestedParentheses(): void 'version' => 'master|\d+\.(?:\d+|x)', 'page' => '[a-z0-9-]+', ]); - $routes->get('docs/(:version)/(:page)', static function () { + $routes->get('docs/(:version)/(:page)', static function (): void { echo 'Test the documentation segment'; }, ['as' => 'docs.version']); diff --git a/tests/system/HotReloader/DirectoryHasherTest.php b/tests/system/HotReloader/DirectoryHasherTest.php index 5ec7d02f9974..4df7e69fd924 100644 --- a/tests/system/HotReloader/DirectoryHasherTest.php +++ b/tests/system/HotReloader/DirectoryHasherTest.php @@ -32,7 +32,7 @@ protected function setUp(): void $this->hasher = new DirectoryHasher(); } - public function testHashApp() + public function testHashApp(): void { $results = $this->hasher->hashApp(); @@ -40,7 +40,7 @@ public function testHashApp() $this->assertArrayHasKey('app', $results); } - public function testHashDirectoryInvalid() + public function testHashDirectoryInvalid(): void { $this->expectException(FrameworkException::class); $this->expectExceptionMessage('Directory does not exist: "' . APPPATH . 'Foo"'); @@ -48,7 +48,7 @@ public function testHashDirectoryInvalid() $this->hasher->hashDirectory(APPPATH . 'Foo'); } - public function testUniqueHashes() + public function testUniqueHashes(): void { $hash1 = $this->hasher->hashDirectory(APPPATH); $hash2 = $this->hasher->hashDirectory(SYSTEMPATH); @@ -56,7 +56,7 @@ public function testUniqueHashes() $this->assertNotSame($hash1, $hash2); } - public function testRepeatableHashes() + public function testRepeatableHashes(): void { $hash1 = $this->hasher->hashDirectory(APPPATH); $hash2 = $this->hasher->hashDirectory(APPPATH); @@ -64,7 +64,7 @@ public function testRepeatableHashes() $this->assertSame($hash1, $hash2); } - public function testHash() + public function testHash(): void { $expected = md5(implode('', $this->hasher->hashApp())); diff --git a/tests/system/I18n/TimeLegacyTest.php b/tests/system/I18n/TimeLegacyTest.php index 8f0fec545e47..f966e3750ce9 100644 --- a/tests/system/I18n/TimeLegacyTest.php +++ b/tests/system/I18n/TimeLegacyTest.php @@ -1130,7 +1130,7 @@ public function testGetter(): void $this->assertNull($time->weekOfWeek); } - public function testUnserializeTimeObject() + public function testUnserializeTimeObject(): void { $time1 = new TimeLegacy('August 28, 2020 10:04:00pm', 'Asia/Manila', 'en'); $timeCache = serialize($time1); diff --git a/tests/system/I18n/TimeTest.php b/tests/system/I18n/TimeTest.php index b81c8ae299af..8e85e8cff3e3 100644 --- a/tests/system/I18n/TimeTest.php +++ b/tests/system/I18n/TimeTest.php @@ -1137,7 +1137,7 @@ public function testGetter(): void $this->assertNull($time->weekOfWeek); } - public function testUnserializeTimeObject() + public function testUnserializeTimeObject(): void { $time1 = new Time('August 28, 2020 10:04:00pm', 'Asia/Manila', 'en'); $timeCache = serialize($time1); diff --git a/tests/system/Models/WhenWhenNotModelTest.php b/tests/system/Models/WhenWhenNotModelTest.php index 003ccd02244d..3039fc0b57b5 100644 --- a/tests/system/Models/WhenWhenNotModelTest.php +++ b/tests/system/Models/WhenWhenNotModelTest.php @@ -42,7 +42,7 @@ public function testWhenWithTrueCondition(): void $this->createModel(SecondaryModel::class)->insertBatch($secondaryData); - $result = $this->model->when($filter, static function ($query, $filter) { + $result = $this->model->when($filter, static function ($query, $filter): void { $query->where('value', $filter); })->find(); @@ -71,9 +71,9 @@ public function testWhenWithFalseConditionAndDefaultCallback(): void $this->createModel(SecondaryModel::class)->insertBatch($secondaryData); - $result = $this->model->when($filter, static function ($query, $filter) { + $result = $this->model->when($filter, static function ($query, $filter): void { $query->where('value', $filter); - }, static function ($query) { + }, static function ($query): void { $query->where('value', 'foobar'); })->find(); @@ -102,7 +102,7 @@ public function testWhenNotWithFalseCondition(): void $this->createModel(SecondaryModel::class)->insertBatch($secondaryData); - $result = $this->model->whenNot($filter, static function ($query, $filter) { + $result = $this->model->whenNot($filter, static function ($query, $filter): void { $query->where('value !=', 'foobar'); })->find(); @@ -131,9 +131,9 @@ public function testWhenNotWithTrueConditionAndDefaultCallback(): void $this->createModel(SecondaryModel::class)->insertBatch($secondaryData); - $result = $this->model->whenNot($filter, static function ($query, $filter) { + $result = $this->model->whenNot($filter, static function ($query, $filter): void { $query->where('value !=', 'foobar'); - }, static function ($query) { + }, static function ($query): void { $query->where('value', 'foobar'); })->find(); diff --git a/tests/system/Router/AutoRouterImprovedTest.php b/tests/system/Router/AutoRouterImprovedTest.php index 1441e2ca49e9..6c531db06a8b 100644 --- a/tests/system/Router/AutoRouterImprovedTest.php +++ b/tests/system/Router/AutoRouterImprovedTest.php @@ -75,7 +75,7 @@ public function testAutoRouteFindsDefaultControllerAndMethodGet(): void ], $router->getPos()); } - public function testAutoRouteFindsModuleDefaultControllerAndMethodGet() + public function testAutoRouteFindsModuleDefaultControllerAndMethodGet(): void { $config = config(Routing::class); $config->moduleRoutes = [ @@ -190,7 +190,7 @@ public function testAutoRouteFindsControllerWithSubfolder(): void ], $router->getPos()); } - public function testAutoRouteFindsControllerWithSubSubfolder() + public function testAutoRouteFindsControllerWithSubSubfolder(): void { $router = $this->createNewAutoRouter(); @@ -258,7 +258,7 @@ public function testAutoRouteFindsDefaultDashFolder(): void $this->assertSame([], $params); } - public function testAutoRouteFallbackToDefaultMethod() + public function testAutoRouteFallbackToDefaultMethod(): void { $router = $this->createNewAutoRouter(); @@ -276,7 +276,7 @@ public function testAutoRouteFallbackToDefaultMethod() ], $router->getPos()); } - public function testAutoRouteFallbackToDefaultControllerOneParam() + public function testAutoRouteFallbackToDefaultControllerOneParam(): void { $router = $this->createNewAutoRouter(); @@ -294,7 +294,7 @@ public function testAutoRouteFallbackToDefaultControllerOneParam() ], $router->getPos()); } - public function testAutoRouteFallbackToDefaultControllerTwoParams() + public function testAutoRouteFallbackToDefaultControllerTwoParams(): void { $router = $this->createNewAutoRouter(); @@ -312,7 +312,7 @@ public function testAutoRouteFallbackToDefaultControllerTwoParams() ], $router->getPos()); } - public function testAutoRouteFallbackToDefaultControllerNoParams() + public function testAutoRouteFallbackToDefaultControllerNoParams(): void { $router = $this->createNewAutoRouter(); @@ -396,7 +396,7 @@ public function testRejectsControllerWithRemapMethod(): void $router->getRoute('remap/test', Method::GET); } - public function testRejectsURIWithUnderscoreFolder() + public function testRejectsURIWithUnderscoreFolder(): void { $this->expectException(PageNotFoundException::class); $this->expectExceptionMessage( @@ -408,7 +408,7 @@ public function testRejectsURIWithUnderscoreFolder() $router->getRoute('dash_folder', Method::GET); } - public function testRejectsURIWithUnderscoreController() + public function testRejectsURIWithUnderscoreController(): void { $this->expectException(PageNotFoundException::class); $this->expectExceptionMessage( @@ -420,7 +420,7 @@ public function testRejectsURIWithUnderscoreController() $router->getRoute('dash-folder/dash_controller/dash-method', Method::GET); } - public function testRejectsURIWithUnderscoreMethod() + public function testRejectsURIWithUnderscoreMethod(): void { $this->expectException(PageNotFoundException::class); $this->expectExceptionMessage( @@ -432,7 +432,7 @@ public function testRejectsURIWithUnderscoreMethod() $router->getRoute('dash-folder/dash-controller/dash_method', Method::GET); } - public function testPermitsURIWithUnderscoreParam() + public function testPermitsURIWithUnderscoreParam(): void { $router = $this->createNewAutoRouter(); @@ -445,7 +445,7 @@ public function testPermitsURIWithUnderscoreParam() $this->assertSame(['a_b'], $params); } - public function testDoesNotTranslateDashInParam() + public function testDoesNotTranslateDashInParam(): void { $router = $this->createNewAutoRouter(); @@ -469,7 +469,7 @@ public function testTranslateUriToCamelCase( int $controllerPos, ?int $methodPos, ?int $paramPos - ) { + ): void { $config = config(Routing::class); $config->translateUriToCamelCase = true; Factories::injectMock('config', Routing::class, $config); @@ -535,7 +535,7 @@ public static function provideTranslateUriToCamelCase(): iterable /** * @dataProvider provideRejectTranslateUriToCamelCase */ - public function testRejectTranslateUriToCamelCase(string $uri, string $expMsg) + public function testRejectTranslateUriToCamelCase(string $uri, string $expMsg): void { $this->expectException(PageNotFoundException::class); $this->expectExceptionMessage( diff --git a/tests/system/Router/Controllers/Subfolder/Home.php b/tests/system/Router/Controllers/Subfolder/Home.php index 9c28c2004a1b..386a86d81c66 100644 --- a/tests/system/Router/Controllers/Subfolder/Home.php +++ b/tests/system/Router/Controllers/Subfolder/Home.php @@ -17,7 +17,7 @@ class Home extends Controller { - public function getIndex($p1 = null, $p2 = null) + public function getIndex($p1 = null, $p2 = null): void { } } diff --git a/tests/system/Router/Controllers/Subfolder/Sub/Mycontroller.php b/tests/system/Router/Controllers/Subfolder/Sub/Mycontroller.php index 6329369a60bb..f13003511e34 100644 --- a/tests/system/Router/Controllers/Subfolder/Sub/Mycontroller.php +++ b/tests/system/Router/Controllers/Subfolder/Sub/Mycontroller.php @@ -17,7 +17,7 @@ class Mycontroller extends Controller { - public function getSomemethod() + public function getSomemethod(): void { } } diff --git a/tests/system/Router/DefinedRouteCollectorTest.php b/tests/system/Router/DefinedRouteCollectorTest.php index 7daf331340e7..779639204ded 100644 --- a/tests/system/Router/DefinedRouteCollectorTest.php +++ b/tests/system/Router/DefinedRouteCollectorTest.php @@ -46,7 +46,7 @@ private function createRouteCollection(array $config = [], $moduleConfig = null) return (new RouteCollection($loader, $moduleConfig, new Routing()))->setHTTPVerb(Method::GET); } - public function testCollect() + public function testCollect(): void { $routes = $this->createRouteCollection(); $routes->get('journals', 'Blogs'); @@ -94,7 +94,7 @@ public function testCollect() /** * @see https://github.com/codeigniter4/CodeIgniter4/issues/8039 */ - public function testCollectSameFromWithDifferentVerb() + public function testCollectSameFromWithDifferentVerb(): void { $routes = $this->createRouteCollection(); $routes->get('login', 'AuthController::showLogin', ['as' => 'loginShow']); diff --git a/tests/system/Router/RouteCollectionTest.php b/tests/system/Router/RouteCollectionTest.php index 86b3c8ba8d89..400f9a99ca29 100644 --- a/tests/system/Router/RouteCollectionTest.php +++ b/tests/system/Router/RouteCollectionTest.php @@ -348,12 +348,12 @@ public function testGroupNestedWithOuterOptionsWithoutInnerOptions(): void $routes->group( 'admin', ['namespace' => 'Admin', 'filter' => ['csrf']], - static function ($routes) { - $routes->get('dashboard', static function () { + static function ($routes): void { + $routes->get('dashboard', static function (): void { }); - $routes->group('profile', static function ($routes) { - $routes->get('/', static function () { + $routes->group('profile', static function ($routes): void { + $routes->get('/', static function (): void { }); }); } @@ -379,15 +379,15 @@ public function testGroupNestedWithOuterAndInnerOption(): void $routes->group( 'admin', ['filter' => ['csrf']], - static function ($routes) { - $routes->get('dashboard', static function () { + static function ($routes): void { + $routes->get('dashboard', static function (): void { }); $routes->group( 'profile', ['filter' => ['honeypot']], - static function ($routes) { - $routes->get('/', static function () { + static function ($routes): void { + $routes->get('/', static function (): void { }); } ); @@ -412,15 +412,15 @@ public function testGroupNestedWithoutOuterOptionWithInnerOption(): void $routes->group( 'admin', ['filter' => 'csrf'], - static function ($routes) { - $routes->get('dashboard', static function () { + static function ($routes): void { + $routes->get('dashboard', static function (): void { }); $routes->group( 'profile', ['namespace' => 'Admin'], - static function ($routes) { - $routes->get('/', static function () { + static function ($routes): void { + $routes->get('/', static function (): void { }); } ); diff --git a/tests/system/Security/CheckPhpIniTest.php b/tests/system/Security/CheckPhpIniTest.php index 847f9fd82897..9028a676ca90 100644 --- a/tests/system/Security/CheckPhpIniTest.php +++ b/tests/system/Security/CheckPhpIniTest.php @@ -24,7 +24,7 @@ */ final class CheckPhpIniTest extends CIUnitTestCase { - public function testCheckIni() + public function testCheckIni(): void { $output = CheckPhpIni::checkIni(); @@ -37,7 +37,7 @@ public function testCheckIni() $this->assertSame($expected, $output['display_errors']); } - public function testRunCli() + public function testRunCli(): void { // Set MockInputOutput to CLI. $io = new MockInputOutput(); @@ -54,7 +54,7 @@ public function testRunCli() CLI::resetInputOutput(); } - public function testRunWeb() + public function testRunWeb(): void { $output = CheckPhpIni::run(false); diff --git a/tests/system/SuperglobalsTest.php b/tests/system/SuperglobalsTest.php index ee526f230614..54ab69958ec4 100644 --- a/tests/system/SuperglobalsTest.php +++ b/tests/system/SuperglobalsTest.php @@ -22,7 +22,7 @@ */ final class SuperglobalsTest extends CIUnitTestCase { - public function testSetGet() + public function testSetGet(): void { $globals = new Superglobals([], []); diff --git a/tests/system/Test/ControllerTestTraitTest.php b/tests/system/Test/ControllerTestTraitTest.php index 26c356116db5..94146215bc13 100644 --- a/tests/system/Test/ControllerTestTraitTest.php +++ b/tests/system/Test/ControllerTestTraitTest.php @@ -272,7 +272,7 @@ public function throwsBody(): never $this->withBody('banana')->execute('throwsBody'); } - public function testWithUriUpdatesUriStringAndCurrentUrlValues() + public function testWithUriUpdatesUriStringAndCurrentUrlValues(): void { $result = $this->withURI('http://example.com/foo/bar/1/2/3') ->controller(Newautorouting::class) diff --git a/tests/system/Test/FeatureTestTraitTest.php b/tests/system/Test/FeatureTestTraitTest.php index bab25613b805..bd746c7a9c57 100644 --- a/tests/system/Test/FeatureTestTraitTest.php +++ b/tests/system/Test/FeatureTestTraitTest.php @@ -99,13 +99,13 @@ public function testCallGetAndFilterReturnsResponse(): void $response->assertRedirectTo('login'); } - public function testClosureWithEcho() + public function testClosureWithEcho(): void { $this->withRoutes([ [ 'GET', 'home', - static function () { echo 'test echo'; }, + static function (): void { echo 'test echo'; }, ], ]); @@ -639,7 +639,7 @@ public function testSetupRequestBodyWithBody(): void $this->assertSame('test', $request->getBody()); } - public function testAutoRoutingLegacy() + public function testAutoRoutingLegacy(): void { $config = config(Routing::class); $config->autoRoute = true; @@ -650,7 +650,7 @@ public function testAutoRoutingLegacy() $response->assertOK(); } - public function testForceGlobalSecureRequests() + public function testForceGlobalSecureRequests(): void { $config = config(App::class); $config->forceGlobalSecureRequests = true; diff --git a/tests/system/Validation/DotArrayFilterTest.php b/tests/system/Validation/DotArrayFilterTest.php index abbd7011ad77..67274860ed35 100644 --- a/tests/system/Validation/DotArrayFilterTest.php +++ b/tests/system/Validation/DotArrayFilterTest.php @@ -22,7 +22,7 @@ */ final class DotArrayFilterTest extends CIUnitTestCase { - public function testRunReturnEmptyArray() + public function testRunReturnEmptyArray(): void { $data = []; @@ -31,7 +31,7 @@ public function testRunReturnEmptyArray() $this->assertSame([], $result); } - public function testRunReturnEmptyArrayMissingValue() + public function testRunReturnEmptyArrayMissingValue(): void { $data = [ 'foo' => [ @@ -44,7 +44,7 @@ public function testRunReturnEmptyArrayMissingValue() $this->assertSame([], $result); } - public function testRunReturnEmptyArrayEmptyIndex() + public function testRunReturnEmptyArrayEmptyIndex(): void { $data = [ 'foo' => [ @@ -57,7 +57,7 @@ public function testRunReturnEmptyArrayEmptyIndex() $this->assertSame([], $result); } - public function testRunEarlyIndex() + public function testRunEarlyIndex(): void { $data = [ 'foo' => [ @@ -70,7 +70,7 @@ public function testRunEarlyIndex() $this->assertSame($data, $result); } - public function testRunWildcard() + public function testRunWildcard(): void { $data = [ 'foo' => [ @@ -85,7 +85,7 @@ public function testRunWildcard() $this->assertSame($data, $result); } - public function testRunWildcardWithMultipleChoices() + public function testRunWildcardWithMultipleChoices(): void { $data = [ 'foo' => [ @@ -103,7 +103,7 @@ public function testRunWildcardWithMultipleChoices() $this->assertSame($data, $result); } - public function testRunNestedNotFound() + public function testRunNestedNotFound(): void { $data = [ 'foo' => [ @@ -121,7 +121,7 @@ public function testRunNestedNotFound() $this->assertSame([], $result); } - public function testRunIgnoresLastWildcard() + public function testRunIgnoresLastWildcard(): void { $data = [ 'foo' => [ @@ -136,7 +136,7 @@ public function testRunIgnoresLastWildcard() $this->assertSame($data, $result); } - public function testRunNestedArray() + public function testRunNestedArray(): void { $array = [ 'user' => [ @@ -183,7 +183,7 @@ public function testRunNestedArray() $this->assertSame($expected, $result); } - public function testRunReturnOrderedIndices() + public function testRunReturnOrderedIndices(): void { $data = [ 'foo' => [ diff --git a/tests/system/View/ViewTest.php b/tests/system/View/ViewTest.php index 18faf053a478..996db86be92a 100644 --- a/tests/system/View/ViewTest.php +++ b/tests/system/View/ViewTest.php @@ -390,7 +390,7 @@ public function testRenderNestedSections(): void $this->assertStringContainsString('

Third

', $content); } - public function testRenderSectionSavingData() + public function testRenderSectionSavingData(): void { $view = new View($this->config, $this->viewsDir, $this->loader); $expected = "Welcome to CodeIgniter 4!\n

Welcome to CodeIgniter 4!

\n

Hello World

"; From 7008a2df578e11a08b95f3acd1652ac8f6124ab7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 10:11:08 +0900 Subject: [PATCH 20/92] test: add test to define() and get() --- tests/system/Config/FactoriesTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/system/Config/FactoriesTest.php b/tests/system/Config/FactoriesTest.php index f40b0968fb74..d2a2ffb212af 100644 --- a/tests/system/Config/FactoriesTest.php +++ b/tests/system/Config/FactoriesTest.php @@ -411,6 +411,19 @@ public function testDefineAndLoad() $this->assertInstanceOf(EntityModel::class, $model); } + public function testDefineAndGet(): void + { + Factories::define( + 'models', + UserModel::class, + EntityModel::class + ); + + $model = Factories::get('models', UserModel::class); + + $this->assertInstanceOf(EntityModel::class, $model); + } + public function testGetComponentInstances() { Factories::config('App'); From ca66cb766d277f5505f014cca2937b07aad666fe Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 10:11:40 +0900 Subject: [PATCH 21/92] fix: Factories::get() cannot get defined classes --- system/Config/Factories.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/system/Config/Factories.php b/system/Config/Factories.php index f8102118bc1d..d98664a24a7b 100644 --- a/system/Config/Factories.php +++ b/system/Config/Factories.php @@ -180,7 +180,9 @@ public static function get(string $component, string $alias): ?object if (isset(self::$aliases[$component][$alias])) { $class = self::$aliases[$component][$alias]; - return self::$instances[$component][$class]; + if (isset(self::$instances[$component][$class])) { + return self::$instances[$component][$class]; + } } return self::__callStatic($component, [$alias]); From cc5eec1643e1b9344e1c7c8191baeb1165cf4f8f Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 11:33:24 +0900 Subject: [PATCH 22/92] chore: add php-cs-fixer config for tests --- .php-cs-fixer.dist.php | 5 +--- .php-cs-fixer.tests.php | 57 +++++++++++++++++++++++++++++++++++++++++ composer.json | 2 ++ 3 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 .php-cs-fixer.tests.php diff --git a/.php-cs-fixer.dist.php b/.php-cs-fixer.dist.php index 807cd0078e7d..b47b4d6480c9 100644 --- a/.php-cs-fixer.dist.php +++ b/.php-cs-fixer.dist.php @@ -21,7 +21,6 @@ ->files() ->in([ __DIR__ . '/system', - __DIR__ . '/tests', __DIR__ . '/utils', ]) ->exclude([ @@ -30,14 +29,12 @@ 'Validation/Views', ]) ->notPath([ - '_support/View/Cells/multiplier.php', - '_support/View/Cells/colors.php', - '_support/View/Cells/addition.php', ]) ->notName('#Foobar.php$#') ->append([ __FILE__, __DIR__ . '/.php-cs-fixer.no-header.php', + __DIR__ . '/.php-cs-fixer.tests.php', __DIR__ . '/.php-cs-fixer.user-guide.php', __DIR__ . '/rector.php', __DIR__ . '/spark', diff --git a/.php-cs-fixer.tests.php b/.php-cs-fixer.tests.php new file mode 100644 index 000000000000..c6b13a135a7c --- /dev/null +++ b/.php-cs-fixer.tests.php @@ -0,0 +1,57 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +use CodeIgniter\CodingStandard\CodeIgniter4; +use Nexus\CsConfig\Factory; +use Nexus\CsConfig\Fixer\Comment\NoCodeSeparatorCommentFixer; +use Nexus\CsConfig\FixerGenerator; +use PhpCsFixer\Finder; + +$finder = Finder::create() + ->files() + ->in([ + __DIR__ . '/tests', + ]) + ->exclude([ + ]) + ->notPath([ + '_support/View/Cells/multiplier.php', + '_support/View/Cells/colors.php', + '_support/View/Cells/addition.php', + ]) + ->notName('#Foobar.php$#') + ->append([ + ]); + +$overrides = [ + 'void_return' => true, +]; + +$options = [ + 'cacheFile' => 'build/.php-cs-fixer.tests.cache', + 'finder' => $finder, +]; + +$config = Factory::create(new CodeIgniter4(), $overrides, $options)->forLibrary( + 'CodeIgniter 4 framework', + 'CodeIgniter Foundation', + 'admin@codeigniter.com' +); + +$config + ->registerCustomFixers(FixerGenerator::create('vendor/nexusphp/cs-config/src/Fixer', 'Nexus\\CsConfig\\Fixer')) + ->setRules(array_merge($config->getRules(), [ + NoCodeSeparatorCommentFixer::name() => true, + ])); + +return $config; diff --git a/composer.json b/composer.json index 9c17f59ded32..bed54690aa96 100644 --- a/composer.json +++ b/composer.json @@ -101,12 +101,14 @@ "Composer\\Config::disableProcessTimeout", "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.user-guide.php", "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.no-header.php", + "php-cs-fixer fix --ansi --verbose --dry-run --diff --config=.php-cs-fixer.tests.php", "php-cs-fixer fix --ansi --verbose --dry-run --diff" ], "cs-fix": [ "Composer\\Config::disableProcessTimeout", "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.user-guide.php", "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.no-header.php", + "php-cs-fixer fix --ansi --verbose --diff --config=.php-cs-fixer.tests.php", "php-cs-fixer fix --ansi --verbose --diff" ], "metrics": "tools/phpmetrics/vendor/bin/phpmetrics --config=phpmetrics.json", From fa5496c9bff42d3837a0d2a54b593cd0041dd6db Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 11:37:43 +0900 Subject: [PATCH 23/92] chore: vendor/bin/phpstan analyze --generate-baseline phpstan-baseline.php --- phpstan-baseline.php | 786 +------------------------------------------ 1 file changed, 13 insertions(+), 773 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 9c5c98a51e45..ea819cb064e2 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -10486,26 +10486,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/_support/Models/UserModel.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Services\\\\Translation\\\\Nested\\\\TranslationFour\\:\\:list\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Services/Translation/TranslationNested/TranslationFour.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Services\\\\Translation\\\\TranslationOne\\:\\:list\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Services/Translation/TranslationOne.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Services\\\\Translation\\\\TranslationThree\\:\\:list\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Services/Translation/TranslationThree.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Services\\\\Translation\\\\TranslationTwo\\:\\:list\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Services/Translation/TranslationTwo.php', -]; $ignoreErrors[] = [ 'message' => '#^Property Tests\\\\Support\\\\SomeEntity\\:\\:\\$attributes type has no value type specified in iterable type array\\.$#', 'count' => 1, @@ -11061,11 +11041,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Autoloader/FileLocatorCachedTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Autoloader\\\\FileLocatorCachedTest\\:\\:testDeleteCache\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Autoloader/FileLocatorCachedTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Assigning 3 directly on offset \'argc\' of \\$_SERVER is discouraged\\.$#', 'count' => 1, @@ -11151,26 +11126,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\FactoriesCacheFileVarExportHandlerTest\\:\\:testDelete\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\FactoriesCacheFileVarExportHandlerTest\\:\\:testInstantiate\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\FactoriesCacheFileVarExportHandlerTest\\:\\:testLoad\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\FactoriesCacheFileVarExportHandlerTest\\:\\:testSave\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/FactoriesCacheFileVarExportHandlerTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Cache\\\\Handlers\\\\BaseHandlerTest\\:\\:provideValidateKeyInvalidType\\(\\) return type has no value type specified in iterable type iterable\\.$#', 'count' => 1, @@ -11261,36 +11216,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\ResponseCacheTest\\:\\:testCachePageCLIRequest\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\ResponseCacheTest\\:\\:testCachePageIncomingRequest\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\ResponseCacheTest\\:\\:testCachePageIncomingRequestWithCacheQueryString\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\ResponseCacheTest\\:\\:testCachePageIncomingRequestWithHttpMethods\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\ResponseCacheTest\\:\\:testInvalidCacheError\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Cache\\\\ResponseCacheTest\\:\\:testUnserializeError\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Cache/ResponseCacheTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Re\\-assigning arrays to \\$_GET directly is discouraged\\.$#', 'count' => 3, @@ -11426,11 +11351,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/CodeIgniterTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CodeIgniterTest\\:\\:testOutputBufferingControl\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/CodeIgniterTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\CodeIgniterTest\\:\\:testPageCacheWithCacheQueryString\\(\\) has parameter \\$cacheQueryStringValue with no value type specified in iterable type array\\.$#', 'count' => 1, @@ -11441,11 +11361,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/CodeIgniterTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CodeIgniterTest\\:\\:testRegisterSameFilterTwiceWithDifferentArgument\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/CodeIgniterTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#2 \\$to of method CodeIgniter\\\\Router\\\\RouteCollection\\:\\:add\\(\\) expects array\\|\\(Closure\\(mixed \\.\\.\\.\\)\\: \\(CodeIgniter\\\\HTTP\\\\ResponseInterface\\|string\\|void\\)\\)\\|string, Closure\\(mixed\\)\\: \\(CodeIgniter\\\\HTTP\\\\DownloadResponse\\|null\\) given\\.$#', 'count' => 1, @@ -11546,16 +11461,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Commands/RoutesTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\RoutesTest\\:\\:testRoutesCommandHostHostname\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Commands/RoutesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\RoutesTest\\:\\:testRoutesCommandHostSubdomain\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Commands/RoutesTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#2 \\$mock of static method CodeIgniter\\\\Config\\\\BaseService\\:\\:injectMock\\(\\) expects object, null given\\.$#', 'count' => 4, @@ -11586,16 +11491,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Commands/Utilities/ConfigCheckTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\ConfigCheckTest\\:\\:testGetKintD\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Commands/Utilities/ConfigCheckTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\ConfigCheckTest\\:\\:testGetVarDump\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Commands/Utilities/ConfigCheckTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\NamespacesTest\\:\\:getBuffer\\(\\) has no return type specified\\.$#', 'count' => 1, @@ -11641,16 +11536,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Commands/Utilities/Routes/FilterFinderTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\FilterFinderTest\\:\\:testFilterOrder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Commands/Utilities/Routes/FilterFinderTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\FilterFinderTest\\:\\:testFilterOrderWithOldFilterOrder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Commands/Utilities/Routes/FilterFinderTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Property CodeIgniter\\\\Commands\\\\Utilities\\\\Routes\\\\FilterFinderTest\\:\\:\\$response \\(CodeIgniter\\\\HTTP\\\\Response\\) does not accept CodeIgniter\\\\HTTP\\\\ResponseInterface\\.$#', 'count' => 1, @@ -11691,16 +11576,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/CommonFunctionsTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CommonFunctionsTest\\:\\:disableHtml5\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/CommonFunctionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CommonFunctionsTest\\:\\:enableHtml5\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/CommonFunctionsTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\CommonFunctionsTest\\:\\:provideCleanPathActuallyCleaningThePaths\\(\\) return type has no value type specified in iterable type iterable\\.$#', 'count' => 1, @@ -11841,71 +11716,11 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testCanLoadSharedConfigWithDifferentAlias\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testCanLoadTwoCellsWithSameShortName\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testDefineAfterLoading\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testDefineAndLoad\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testDefineNonExistentClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testDefineSameAliasAndSameClassTwice\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testDefineSameAliasTwiceWithDifferentClasses\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testFullClassnameIgnoresPreferApp\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testGetComponentInstances\\(\\) has no return type specified\\.$#', 'count' => 1, 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testGetCreatesConfigInstanceAndFactoriesConfigReturnsIt\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testGetNonexistentClass\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testGetReturnsFactoriesConfigInstance\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testIsUpdated\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testIsUpdated\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#', 'count' => 1, @@ -11921,11 +11736,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Config\\\\FactoriesTest\\:\\:testShortnameReturnsConfigInApp\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Config/FactoriesTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$expected of method PHPUnit\\\\Framework\\\\Assert\\:\\:assertInstanceOf\\(\\) expects class\\-string\\, string given\\.$#', 'count' => 1, @@ -12251,31 +12061,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/DataConverter/DataConverterTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\DataConverter\\\\DataConverterTest\\:\\:testExtract\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/DataConverter/DataConverterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\DataConverter\\\\DataConverterTest\\:\\:testExtractWithClosure\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/DataConverter/DataConverterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\DataConverter\\\\DataConverterTest\\:\\:testExtractWithExtractMethod\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/DataConverter/DataConverterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\DataConverter\\\\DataConverterTest\\:\\:testReconstructObjectWithClosure\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/DataConverter/DataConverterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\DataConverter\\\\DataConverterTest\\:\\:testReconstructObjectWithReconstructMethod\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/DataConverter/DataConverterTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Access to an undefined property CodeIgniter\\\\Test\\\\Mock\\\\MockConnection\\:\\:\\$foobar\\.$#', 'count' => 1, @@ -12441,11 +12226,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Database/Live/FabricatorLiveTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\ForgeTest\\:\\:testAddColumnNull\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Database/Live/ForgeTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$fields of method CodeIgniter\\\\Database\\\\Forge\\:\\:addField\\(\\) expects array\\\\|string, array\\ given\\.$#', 'count' => 2, @@ -12521,26 +12301,6 @@ 'count' => 2, 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:testDisableNumberNative\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:testEnableNumberNative\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:testQueryDataAfterDisableNumberNative\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:testQueryDataAfterEnableNumberNative\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Property CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:\\$tests has no type specified\\.$#', 'count' => 1, @@ -12826,21 +12586,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Entity/EntityTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Entity\\\\EntityTest\\:\\:testNewGetterSetters\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Entity/EntityTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Entity\\\\EntityTest\\:\\:testSetArrayToPropertyNamedAttributes\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Entity/EntityTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Entity\\\\EntityTest\\:\\:testSetStringToPropertyNamedAttributes\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Entity/EntityTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method class@anonymous/tests/system/Entity/EntityTest\\.php\\:1078\\:\\:getBar\\(\\) has no return type specified\\.$#', 'count' => 1, @@ -13056,21 +12801,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Filters/FiltersTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Filters\\\\FiltersTest\\:\\:testFilterWithArgumentsIsDefined\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Filters/FiltersTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Filters\\\\FiltersTest\\:\\:testFilterWithoutArgumentsIsDefined\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Filters/FiltersTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Filters\\\\FiltersTest\\:\\:testFiltersWithArguments\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Filters/FiltersTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Filters\\\\FiltersTest\\:\\:testProcessMethodProcessGlobalsWithExcept\\(\\) has parameter \\$except with no value type specified in iterable type array\\.$#', 'count' => 1, @@ -13236,11 +12966,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestDoNotShareOptionsTest\\:\\:testProxyuOption\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Access to an undefined property CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:\\$curl_options\\.$#', 'count' => 39, @@ -13281,11 +13006,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestTest\\:\\:testProxyuOption\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\ContentSecurityPolicyTest\\:\\:work\\(\\) has no return type specified\\.$#', 'count' => 1, @@ -13306,16 +13026,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/Files/FileCollectionTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\Files\\\\FileCollectionTest\\:\\:testClientPathReturnsNullWhenFullPathIsNull\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/Files/FileCollectionTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\Files\\\\FileCollectionTest\\:\\:testClientPathReturnsValidFullPath\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/Files/FileCollectionTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Function CodeIgniter\\\\HTTP\\\\Files\\\\is_uploaded_file\\(\\) has no return type specified\\.$#', 'count' => 1, @@ -13656,11 +13366,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/IncomingRequestTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\IncomingRequestTest\\:\\:testSetValidLocales\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/IncomingRequestTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Property Config\\\\App\\:\\:\\$proxyIPs \\(array\\\\) does not accept array\\\\.$#', 'count' => 1, @@ -13987,124 +13692,29 @@ 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testDefault\\(\\) has no return type specified\\.$#', + 'message' => '#^Re\\-assigning arrays to \\$_GET directly is discouraged\\.$#', 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testDefaultEmpty\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', + 'message' => '#^Assigning \'/index\\.php\' directly on offset \'SCRIPT_NAME\' of \\$_SERVER is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testExtensionPHP\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', + 'message' => '#^Assigning \'/index\\.php/woot\\?code\\=good\' directly on offset \'REQUEST_URI\' of \\$_SERVER is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testPathInfoSubfolder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', + 'message' => '#^Assigning \'/woot\' directly on offset \'PATH_INFO\' of \\$_SERVER is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testPathInfoUnset\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testQueryString\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testQueryStringEmpty\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testQueryStringWithQueryString\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURI\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURIGetPath\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURINested\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURINginx\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURINginxRedirecting\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURINoIndex\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURIPathIsNeverRediscovered\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURIPathIsRelative\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURIStoresDetectedPath\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURISubfolder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testRequestURISuppressed\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Re\\-assigning arrays to \\$_GET directly is discouraged\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'/index\\.php\' directly on offset \'SCRIPT_NAME\' of \\$_SERVER is discouraged\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'/index\\.php/woot\\?code\\=good\' directly on offset \'REQUEST_URI\' of \\$_SERVER is discouraged\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'/woot\' directly on offset \'PATH_INFO\' of \\$_SERVER is discouraged\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'code\\=good\' directly on offset \'QUERY_STRING\' of \\$_SERVER is discouraged\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', + 'message' => '#^Assigning \'code\\=good\' directly on offset \'QUERY_STRING\' of \\$_SERVER is discouraged\\.$#', + 'count' => 2, + 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', ]; $ignoreErrors[] = [ 'message' => '#^Assigning \'good\' directly on offset \'code\' of \\$_GET is discouraged\\.$#', @@ -14131,26 +13741,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryTest\\:\\:testCreateFromGlobals\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryTest\\:\\:testCreateFromGlobalsAllowedHost\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryTest\\:\\:testCreateFromStringWithIndexPage\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryTest\\:\\:testCreateFromStringWithoutIndexPage\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Re\\-assigning arrays to \\$_GET directly is discouraged\\.$#', 'count' => 1, @@ -14171,116 +13761,16 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructor\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructor\\(\\) has parameter \\$expectedSegments with no value type specified in iterable type array\\.$#', 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructorEmptyScheme\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructorForceGlobalSecureRequests\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructorHost\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructorInvalidBaseURL\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testConstructorScheme\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testGetBaseURL\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testGetRoutePath\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testGetSegmentOutOfRange\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testGetSegmentZero\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testGetSegments\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testGetTotalSegments\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetBaseURI\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetPath\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetPath\\(\\) has parameter \\$expectedSegments with no value type specified in iterable type array\\.$#', 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetSegment\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetSegmentOutOfRange\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetSegmentSilentOutOfRange\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetSegmentSubfolder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetSegmentZero\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURITest\\:\\:testSetURI\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURITest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#4 \\$scheme of class CodeIgniter\\\\HTTP\\\\SiteURI constructor expects \'http\'\\|\'https\'\\|null, \'\' given\\.$#', 'count' => 1, @@ -14356,21 +13846,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/URITest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\URITest\\:\\:testWithScheme\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/URITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\URITest\\:\\:testWithSchemeSetsEmpty\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/URITest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\URITest\\:\\:testWithSchemeSetsHttps\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/URITest.php', -]; $ignoreErrors[] = [ 'message' => '#^Accessing offset \'HTTP_REFERER\' directly on \\$_SERVER is discouraged\\.$#', 'count' => 1, @@ -14546,31 +14021,11 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Helpers/FilesystemHelperTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Helpers\\\\FormHelperTest\\:\\:disableHtml5\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Helpers/FormHelperTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Helpers\\\\FormHelperTest\\:\\:enableHtml5\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Helpers/FormHelperTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#2 \\$value of function form_hidden expects array\\|string, null given\\.$#', 'count' => 1, 'path' => __DIR__ . '/tests/system/Helpers/FormHelperTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Helpers\\\\HTMLHelperTest\\:\\:disableHtml5\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Helpers/HTMLHelperTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Helpers\\\\HTMLHelperTest\\:\\:enableHtml5\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Helpers/HTMLHelperTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Property CodeIgniter\\\\Helpers\\\\HTMLHelperTest\\:\\:\\$tracks type has no value type specified in iterable type array\\.$#', 'count' => 1, @@ -14931,31 +14386,6 @@ 'count' => 3, 'path' => __DIR__ . '/tests/system/Honeypot/HoneypotTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HotReloader\\\\DirectoryHasherTest\\:\\:testHash\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HotReloader/DirectoryHasherTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HotReloader\\\\DirectoryHasherTest\\:\\:testHashApp\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HotReloader/DirectoryHasherTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HotReloader\\\\DirectoryHasherTest\\:\\:testHashDirectoryInvalid\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HotReloader/DirectoryHasherTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HotReloader\\\\DirectoryHasherTest\\:\\:testRepeatableHashes\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HotReloader/DirectoryHasherTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HotReloader\\\\DirectoryHasherTest\\:\\:testUniqueHashes\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HotReloader/DirectoryHasherTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Access to an undefined property CodeIgniter\\\\I18n\\\\TimeDifference\\:\\:\\$nonsense\\.$#', 'count' => 2, @@ -15016,11 +14446,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/I18n/TimeLegacyTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\I18n\\\\TimeLegacyTest\\:\\:testUnserializeTimeObject\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/I18n/TimeLegacyTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Access to an undefined property CodeIgniter\\\\I18n\\\\Time\\:\\:\\$timezoneName\\.$#', 'count' => 1, @@ -15036,11 +14461,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/I18n/TimeTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\I18n\\\\TimeTest\\:\\:testUnserializeTimeObject\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/I18n/TimeTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Call to an undefined method CodeIgniter\\\\Images\\\\Handlers\\\\BaseHandler\\:\\:getPathname\\(\\)\\.$#', 'count' => 1, @@ -15966,71 +15386,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testAutoRouteFallbackToDefaultControllerNoParams\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testAutoRouteFallbackToDefaultControllerOneParam\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testAutoRouteFallbackToDefaultControllerTwoParams\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testAutoRouteFallbackToDefaultMethod\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testAutoRouteFindsControllerWithSubSubfolder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testAutoRouteFindsModuleDefaultControllerAndMethodGet\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testDoesNotTranslateDashInParam\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testPermitsURIWithUnderscoreParam\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testRejectTranslateUriToCamelCase\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testRejectsURIWithUnderscoreController\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testRejectsURIWithUnderscoreFolder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testRejectsURIWithUnderscoreMethod\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\AutoRouterImprovedTest\\:\\:testTranslateUriToCamelCase\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/AutoRouterImprovedTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Router\\\\Controllers\\\\BlogController\\:\\:getSomeMethod\\(\\) has parameter \\$first with no type specified\\.$#', 'count' => 1, @@ -16056,11 +15411,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Router/Controllers/SubDir/BlogController.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\Controllers\\\\Subfolder\\\\Home\\:\\:getIndex\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/Controllers/Subfolder/Home.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Router\\\\Controllers\\\\Subfolder\\\\Home\\:\\:getIndex\\(\\) has parameter \\$p1 with no type specified\\.$#', 'count' => 1, @@ -16076,11 +15426,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Router/Controllers/Subfolder/Sub/BlogController.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\Controllers\\\\Subfolder\\\\Sub\\\\Mycontroller\\:\\:getSomemethod\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/Controllers/Subfolder/Sub/Mycontroller.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Router\\\\DefinedRouteCollectorTest\\:\\:createRouteCollection\\(\\) has parameter \\$config with no value type specified in iterable type array\\.$#', 'count' => 1, @@ -16091,16 +15436,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Router/DefinedRouteCollectorTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\DefinedRouteCollectorTest\\:\\:testCollect\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/DefinedRouteCollectorTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Router\\\\DefinedRouteCollectorTest\\:\\:testCollectSameFromWithDifferentVerb\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Router/DefinedRouteCollectorTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Router\\\\RouteCollectionReverseRouteTest\\:\\:getCollector\\(\\) has no return type specified\\.$#', 'count' => 1, @@ -16221,21 +15556,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Router/RouterTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Security\\\\CheckPhpIniTest\\:\\:testCheckIni\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Security/CheckPhpIniTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Security\\\\CheckPhpIniTest\\:\\:testRunCli\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Security/CheckPhpIniTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Security\\\\CheckPhpIniTest\\:\\:testRunWeb\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Security/CheckPhpIniTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Assigning \'POST\' directly on offset \'REQUEST_METHOD\' of \\$_SERVER is discouraged\\.$#', 'count' => 1, @@ -16391,11 +15711,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Session/SessionTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\SuperglobalsTest\\:\\:testSetGet\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/SuperglobalsTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Test\\\\BootstrapFCPATHTest\\:\\:correctFCPATH\\(\\) has no return type specified\\.$#', 'count' => 1, @@ -16441,11 +15756,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Test/ControllerTestTraitTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Test\\\\ControllerTestTraitTest\\:\\:testWithUriUpdatesUriStringAndCurrentUrlValues\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Test/ControllerTestTraitTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$config of class CodeIgniter\\\\Log\\\\Logger constructor expects Config\\\\Logger, CodeIgniter\\\\Test\\\\Mock\\\\MockLogger given\\.$#', 'count' => 15, @@ -16666,21 +15976,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Test/FeatureTestTraitTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Test\\\\FeatureTestTraitTest\\:\\:testAutoRoutingLegacy\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Test/FeatureTestTraitTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Test\\\\FeatureTestTraitTest\\:\\:testClosureWithEcho\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Test/FeatureTestTraitTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Test\\\\FeatureTestTraitTest\\:\\:testForceGlobalSecureRequests\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Test/FeatureTestTraitTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Test\\\\FeatureTestTraitTest\\:\\:withHeaders\\(\\) has parameter \\$headers with no value type specified in iterable type array\\.$#', 'count' => 1, @@ -16841,56 +16136,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/Validation/DatabaseRelatedRulesTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunEarlyIndex\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunIgnoresLastWildcard\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunNestedArray\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunNestedNotFound\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunReturnEmptyArray\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunReturnEmptyArrayEmptyIndex\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunReturnEmptyArrayMissingValue\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunReturnOrderedIndices\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunWildcard\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Validation\\\\DotArrayFilterTest\\:\\:testRunWildcardWithMultipleChoices\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Validation/DotArrayFilterTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Parameter \\#1 \\$config of class CodeIgniter\\\\Validation\\\\Validation constructor expects Config\\\\Validation, stdClass given\\.$#', 'count' => 1, @@ -17611,11 +16856,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/View/TableTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\ViewTest\\:\\:testRenderSectionSavingData\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/View/ViewTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Property CodeIgniter\\\\View\\\\ViewTest\\:\\:\\$loader \\(CodeIgniter\\\\Autoloader\\\\FileLocator\\) does not accept CodeIgniter\\\\Autoloader\\\\FileLocatorInterface\\.$#', 'count' => 1, From f7983c15e75162b24cb0977ce5b3e4bad3c1e099 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 10 Apr 2024 11:54:02 +0900 Subject: [PATCH 24/92] docs: change desciption to more appropriate --- user_guide_src/source/installation/upgrade_450.rst | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/installation/upgrade_450.rst b/user_guide_src/source/installation/upgrade_450.rst index dd8bae0713b8..c166c17b5163 100644 --- a/user_guide_src/source/installation/upgrade_450.rst +++ b/user_guide_src/source/installation/upgrade_450.rst @@ -227,8 +227,9 @@ for details. Removed Deprecated Items ======================== -Some deprecated items have been removed. If you extend these classes and are -using them, upgrade your code. See :ref:`ChangeLog ` for details. +Some deprecated items have been removed. If you are still using these items, or +extending these classes, upgrade your code. See :ref:`ChangeLog ` +for details. Breaking Enhancements ********************* From a5213fe13d45aacab25c0b54cbaf1a888ee9bdb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 00:26:20 +0300 Subject: [PATCH 25/92] test: refactor system/CLI/BaseCommand.php --- phpstan-baseline.php | 20 -------------------- system/CLI/BaseCommand.php | 10 +++++++--- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 9c5c98a51e45..1bec8d83965b 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -261,26 +261,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/BaseModel.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 2, - 'path' => __DIR__ . '/system/CLI/BaseCommand.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CLI\\\\BaseCommand\\:\\:__get\\(\\) return type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/CLI/BaseCommand.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CLI\\\\BaseCommand\\:\\:call\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/CLI/BaseCommand.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\CLI\\\\BaseCommand\\:\\:getPad\\(\\) has parameter \\$array with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/CLI/BaseCommand.php', -]; $ignoreErrors[] = [ 'message' => '#^Accessing offset \'ANSICON\' directly on \\$_SERVER is discouraged\\.$#', 'count' => 1, diff --git a/system/CLI/BaseCommand.php b/system/CLI/BaseCommand.php index 1b273846bd74..ffba81c33637 100644 --- a/system/CLI/BaseCommand.php +++ b/system/CLI/BaseCommand.php @@ -108,6 +108,8 @@ abstract public function run(array $params); /** * Can be used by a command to run other commands. * + * @param array $params + * * @return int|void * * @throws ReflectionException @@ -140,7 +142,7 @@ public function showHelp() { CLI::write(lang('CLI.helpUsage'), 'yellow'); - if (! empty($this->usage)) { + if (isset($this->usage)) { $usage = $this->usage; } else { $usage = $this->name; @@ -152,7 +154,7 @@ public function showHelp() CLI::write($this->setPad($usage, 0, 0, 2)); - if (! empty($this->description)) { + if (isset($this->description)) { CLI::newLine(); CLI::write(lang('CLI.helpDescription'), 'yellow'); CLI::write($this->setPad($this->description, 0, 0, 2)); @@ -194,6 +196,8 @@ public function setPad(string $item, int $max, int $extra = 2, int $indent = 0): /** * Get pad for $key => $value array output * + * @param array $array + * * @deprecated Use setPad() instead. * * @codeCoverageIgnore @@ -212,7 +216,7 @@ public function getPad(array $array, int $pad): int /** * Makes it simple to access our protected properties. * - * @return array|Commands|LoggerInterface|string|null + * @return Commands|list|LoggerInterface|string|null */ public function __get(string $key) { From 5aa01a665cbe16d953abda3c57342c6ad02c0e69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=BCller=20Nato?= Date: Wed, 10 Apr 2024 06:44:57 -0300 Subject: [PATCH 26/92] docs: added Config\Feature::$oldFilterOrder to app/Config/Feature.php line added Config\Feature::$oldFilterOrder to app/Config/Feature.php line --- user_guide_src/source/installation/upgrade_450.rst | 2 ++ 1 file changed, 2 insertions(+) diff --git a/user_guide_src/source/installation/upgrade_450.rst b/user_guide_src/source/installation/upgrade_450.rst index dd8bae0713b8..35329c83007f 100644 --- a/user_guide_src/source/installation/upgrade_450.rst +++ b/user_guide_src/source/installation/upgrade_450.rst @@ -322,6 +322,8 @@ Others - The default value of ``DBCollat`` in ``$default`` has been change to ``utf8mb4_general_ci``. - The default value of ``DBCollat`` in ``$tests`` has been change to ``''``. - app/Config/Feature.php + - ``Config\Feature::$oldFilterOrder`` has been added. See + :ref:`filter-execution-order`. - ``Config\Feature::$limitZeroAsAll`` has been added. See :ref:`v450-query-builder-limit-0-behavior`. - ``Config\Feature::$multipleFilters`` has been removed, because now From 2a6591aaa4f17e0348fa2458d546505d9964622c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 14:23:41 +0300 Subject: [PATCH 27/92] Fix doc type ordering in BaseCommand.php following PHPStan guidelines and PR review. --- system/CLI/BaseCommand.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/CLI/BaseCommand.php b/system/CLI/BaseCommand.php index ffba81c33637..86ba504feaa6 100644 --- a/system/CLI/BaseCommand.php +++ b/system/CLI/BaseCommand.php @@ -216,7 +216,7 @@ public function getPad(array $array, int $pad): int /** * Makes it simple to access our protected properties. * - * @return Commands|list|LoggerInterface|string|null + * @return array|Commands|LoggerInterface|string|null */ public function __get(string $key) { From ef715310d92eee4d6a8177f844c1939e00681ef3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 02:10:35 +0300 Subject: [PATCH 28/92] refactor: system/View/Plugins.php --- phpstan-baseline.php | 30 ------------------------------ system/View/Plugins.php | 12 ++++++++++++ 2 files changed, 12 insertions(+), 30 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 9c5c98a51e45..ab5749218f38 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -9751,36 +9751,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/View/Parser.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\Plugins\\:\\:ValidationErrors\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/View/Plugins.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\Plugins\\:\\:lang\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/View/Plugins.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\Plugins\\:\\:mailto\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/View/Plugins.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\Plugins\\:\\:route\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/View/Plugins.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\Plugins\\:\\:safeMailto\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/View/Plugins.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\View\\\\Plugins\\:\\:siteURL\\(\\) has parameter \\$params with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/View/Plugins.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\View\\\\RendererInterface\\:\\:render\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', 'count' => 1, diff --git a/system/View/Plugins.php b/system/View/Plugins.php index da147d097d06..699aa3f61a59 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -42,6 +42,8 @@ public static function previousURL() /** * Wrap helper function to use as view plugin. + * + * @param array{uri?: string, title?: string, attributes?: string} $params */ public static function mailto(array $params = []): string { @@ -54,6 +56,8 @@ public static function mailto(array $params = []): string /** * Wrap helper function to use as view plugin. + * + * @param array{email?: string, title?: string, attributes?: string} $params */ public static function safeMailto(array $params = []): string { @@ -66,6 +70,8 @@ public static function safeMailto(array $params = []): string /** * Wrap helper function to use as view plugin. + * + * @param list $params */ public static function lang(array $params = []): string { @@ -76,6 +82,8 @@ public static function lang(array $params = []): string /** * Wrap helper function to use as view plugin. + * + * @param array{field?: string} $params */ public static function ValidationErrors(array $params = []): string { @@ -90,6 +98,8 @@ public static function ValidationErrors(array $params = []): string /** * Wrap helper function to use as view plugin. * + * @param list $params + * * @return false|string */ public static function route(array $params = []) @@ -99,6 +109,8 @@ public static function route(array $params = []) /** * Wrap helper function to use as view plugin. + * + * @param array{uri?: string, title?: string, attributes?: string} $params */ public static function siteURL(array $params = []): string { From 12b5bfae642bea8b549d014ba1cb822bd18ccfb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 09:10:33 +0300 Subject: [PATCH 29/92] refactor: system/View/Plugins.php --- writable/debugbar/index.html | 11 ----------- 1 file changed, 11 deletions(-) delete mode 100755 writable/debugbar/index.html diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html deleted file mode 100755 index b702fbc3967b..000000000000 --- a/writable/debugbar/index.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 403 Forbidden - - - -

Directory access is forbidden.

- - - From 8ad4279d3e18e22238ddbfa99e4c9f0272cf92ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 10:03:59 +0300 Subject: [PATCH 30/92] Revert index.html --- writable/debugbar/index.html | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 writable/debugbar/index.html diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html new file mode 100644 index 000000000000..69df4e1dff68 --- /dev/null +++ b/writable/debugbar/index.html @@ -0,0 +1,11 @@ + + + + 403 Forbidden + + + +

Directory access is forbidden.

+ + + From 0ccb63fa19c3ccacb09cfdee16bcb57bd4cf81bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 13:32:20 +0300 Subject: [PATCH 31/92] Revert index.html --- writable/debugbar/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html index 69df4e1dff68..b702fbc3967b 100644 --- a/writable/debugbar/index.html +++ b/writable/debugbar/index.html @@ -1,7 +1,7 @@ - 403 Forbidden + 403 Forbidden From 234dba2856aed616ff80b85f492c79d88f7f2cdd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 13:33:33 +0300 Subject: [PATCH 32/92] Revert index.html --- writable/debugbar/index.html | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 writable/debugbar/index.html diff --git a/writable/debugbar/index.html b/writable/debugbar/index.html old mode 100644 new mode 100755 From 393181b26f9138ac4eb32a6df8e11cff4779727d Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:04:04 +0900 Subject: [PATCH 33/92] test: add test to pass Stringable to $db->escape() --- tests/system/Database/Live/EscapeTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index e1b700547c0c..e228c92aea06 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -14,6 +14,7 @@ namespace CodeIgniter\Database\Live; use CodeIgniter\Database\RawSql; +use CodeIgniter\I18n\Time; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; @@ -54,6 +55,14 @@ public function testEscape(): void $this->assertSame($expected, $sql); } + public function testEscapeStringable(): void + { + $expected = "SELECT * FROM brands WHERE name = '2024-01-01 12:00:00'"; + $sql = 'SELECT * FROM brands WHERE name = ' . $this->db->escape(new Time('2024-01-01 12:00:00')); + + $this->assertSame($expected, $sql); + } + public function testEscapeString(): void { $expected = "SELECT * FROM brands WHERE name = 'O" . $this->char . "'Doules'"; From 4ac163dd5be369285339ad4e15b83f0b2885489c Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:04:44 +0900 Subject: [PATCH 34/92] fix: $db->escape() does not accept Stringable --- system/Database/BaseConnection.php | 8 ++++++-- system/Database/Postgre/Connection.php | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index e0bd7bb51217..983e57ec6dda 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -17,6 +17,7 @@ use CodeIgniter\Database\Exceptions\DatabaseException; use CodeIgniter\Events\Events; use stdClass; +use Stringable; use Throwable; /** @@ -1309,12 +1310,15 @@ public function escape($str) return array_map($this->escape(...), $str); } - /** @psalm-suppress NoValue I don't know why ERROR. */ - if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) { + if ($str instanceof Stringable) { if ($str instanceof RawSql) { return $str->__toString(); } + $str = (string) $str; + } + + if (is_string($str)) { return "'" . $this->escapeString($str) . "'"; } diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index 45e30eb65365..bce4209c64d2 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -20,6 +20,7 @@ use PgSql\Connection as PgSqlConnection; use PgSql\Result as PgSqlResult; use stdClass; +use Stringable; /** * Connection for Postgre @@ -233,12 +234,15 @@ public function escape($str) $this->initialize(); } - /** @psalm-suppress NoValue I don't know why ERROR. */ - if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) { + if ($str instanceof Stringable) { if ($str instanceof RawSql) { return $str->__toString(); } + $str = (string) $str; + } + + if (is_string($str)) { return pg_escape_literal($this->connID, $str); } @@ -246,7 +250,6 @@ public function escape($str) return $str ? 'TRUE' : 'FALSE'; } - /** @psalm-suppress NoValue I don't know why ERROR. */ return parent::escape($str); } From 63a8aaa7e751528f1f45176c4d1c884a49370b3f Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:46:17 +0900 Subject: [PATCH 35/92] fix: $db->escapeString() does not accept Stringable --- system/Database/BaseConnection.php | 12 ++++++++++-- tests/system/Database/Live/EscapeTest.php | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 983e57ec6dda..3847b92b255b 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1332,8 +1332,8 @@ public function escape($str) /** * Escape String * - * @param list|string $str Input string - * @param bool $like Whether or not the string will be used in a LIKE condition + * @param list|string|Stringable $str Input string + * @param bool $like Whether the string will be used in a LIKE condition * * @return list|string */ @@ -1347,6 +1347,14 @@ public function escapeString($str, bool $like = false) return $str; } + if ($str instanceof Stringable) { + if ($str instanceof RawSql) { + return $str->__toString(); + } + + $str = (string) $str; + } + $str = $this->_escapeString($str); // escape LIKE condition wildcards diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index e228c92aea06..0f931cdbe85c 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -71,6 +71,15 @@ public function testEscapeString(): void $this->assertSame($expected, $sql); } + public function testEscapeStringStringable(): void + { + $expected = "SELECT * FROM brands WHERE name = '2024-01-01 12:00:00'"; + $sql = "SELECT * FROM brands WHERE name = '" + . $this->db->escapeString(new Time('2024-01-01 12:00:00')) . "'"; + + $this->assertSame($expected, $sql); + } + public function testEscapeLikeString(): void { $expected = "SELECT * FROM brands WHERE column LIKE '%10!% more%' ESCAPE '!'"; @@ -79,6 +88,15 @@ public function testEscapeLikeString(): void $this->assertSame($expected, $sql); } + public function testEscapeLikeStringStringable(): void + { + $expected = "SELECT * FROM brands WHERE column LIKE '%2024-01-01 12:00:00%' ESCAPE '!'"; + $sql = "SELECT * FROM brands WHERE column LIKE '%" + . $this->db->escapeLikeString(new Time('2024-01-01 12:00:00')) . "%' ESCAPE '!'"; + + $this->assertSame($expected, $sql); + } + public function testEscapeLikeStringDirect(): void { if ($this->db->DBDriver === 'MySQLi') { From bd936e38f8a0288a8282078c3fb6b1b3b8133980 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 09:00:49 +0900 Subject: [PATCH 36/92] docs: update @param type --- system/Database/BaseConnection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 3847b92b255b..b597c6d6cd10 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1383,7 +1383,7 @@ public function escapeString($str, bool $like = false) * Calls the individual driver for platform * specific escaping for LIKE conditions * - * @param list|string $str + * @param list|string|Stringable $str * * @return list|string */ From 0337ce37a1b791f423a8c2c0bf4936092b8b78d1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:59:14 +0900 Subject: [PATCH 37/92] docs: replace @preperty with @property-read --- system/I18n/Time.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 2c6f3c4fab70..51d43a6486ab 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -21,22 +21,22 @@ * * Requires the intl PHP extension. * - * @property int $age read-only - * @property string $day read-only - * @property string $dayOfWeek read-only - * @property string $dayOfYear read-only - * @property bool $dst read-only - * @property string $hour read-only - * @property bool $local read-only - * @property string $minute read-only - * @property string $month read-only - * @property string $quarter read-only - * @property string $second read-only - * @property int $timestamp read-only - * @property bool $utc read-only - * @property string $weekOfMonth read-only - * @property string $weekOfYear read-only - * @property string $year read-only + * @property-read int $age + * @property-read string $day + * @property-read string $dayOfWeek + * @property-read string $dayOfYear + * @property-read bool $dst + * @property-read string $hour + * @property-read bool $local + * @property-read string $minute + * @property-read string $month + * @property-read string $quarter + * @property-read string $second + * @property-read int $timestamp + * @property-read bool $utc + * @property-read string $weekOfMonth + * @property-read string $weekOfYear + * @property-read string $year * * @see \CodeIgniter\I18n\TimeTest */ From c1ec70f2b4add77e1b8ec038ba2dd3c477aad1ba Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:59:38 +0900 Subject: [PATCH 38/92] refactor: implement Stringable To fix PHPStan errors. --- system/I18n/Time.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 51d43a6486ab..906479470b17 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -14,6 +14,7 @@ namespace CodeIgniter\I18n; use DateTimeImmutable; +use Stringable; /** * A localized date/time package inspired @@ -40,7 +41,7 @@ * * @see \CodeIgniter\I18n\TimeTest */ -class Time extends DateTimeImmutable +class Time extends DateTimeImmutable implements Stringable { use TimeTrait; } From 51c1ee164fd27ab01785a1c2b9910655304c745d Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 07:00:29 +0900 Subject: [PATCH 39/92] test: add tests for CSRF protection --- tests/system/Helpers/FormHelperTest.php | 163 +++++++++++++++--------- 1 file changed, 102 insertions(+), 61 deletions(-) diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php index 26e9c97fbcfd..c139f263d837 100644 --- a/tests/system/Helpers/FormHelperTest.php +++ b/tests/system/Helpers/FormHelperTest.php @@ -52,25 +52,40 @@ private function setRequest(): void Services::injectMock('request', $request); } + private function setCsrfFilter(): void + { + $filters = config(Filters::class); + $filters->globals['before'][] = 'csrf'; + service('filters')->initialize(); + } + public function testFormOpenBasic(): void { $this->setRequest(); - $before = (new Filters())->globals['before']; - if (in_array('csrf', $before, true) || array_key_exists('csrf', $before)) { - $Value = csrf_hash(); - $Name = csrf_token(); - $expected = << - + $expected = <<<'EOH' + + + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $this->assertSame($expected, form_open('foo/bar', $attributes)); + } - EOH; - } else { - $expected = <<<'EOH' - + public function testFormOpenBasicWithCSRF(): void + { + $this->setRequest(); + $this->setCsrfFilter(); - EOH; - } + $Value = csrf_hash(); + $Name = csrf_token(); + $expected = << + + EOH; $attributes = [ 'name' => 'form', @@ -116,11 +131,7 @@ public function testFormOpenWithoutAction(): void public function testFormOpenWithoutActionWithCSRF(): void { $this->setRequest(); - - // Sets csrf filter. - $filters = config(Filters::class); - $filters->globals['before'][] = 'csrf'; - service('filters')->initialize(); + $this->setCsrfFilter(); $Value = csrf_hash(); $Name = csrf_token(); @@ -140,22 +151,29 @@ public function testFormOpenWithoutMethod(): void { $this->setRequest(); - $before = (new Filters())->globals['before']; - if (in_array('csrf', $before, true) || array_key_exists('csrf', $before)) { - $Value = csrf_hash(); - $Name = csrf_token(); - $expected = << - + $expected = <<<'EOH' + - EOH; - } else { - $expected = <<<'EOH' - + EOH; + + $attributes = [ + 'name' => 'form', + 'id' => 'form', + ]; + $this->assertSame($expected, form_open('foo/bar', $attributes)); + } - EOH; - } + public function testFormOpenWithoutMethodWithCSRF(): void + { + $this->setRequest(); + $this->setCsrfFilter(); + $Value = csrf_hash(); + $Name = csrf_token(); + $expected = << + + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', @@ -167,25 +185,36 @@ public function testFormOpenWithHidden(): void { $this->setRequest(); - $before = (new Filters())->globals['before']; - if (in_array('csrf', $before, true) || array_key_exists('csrf', $before)) { - $Value = csrf_hash(); - $Name = csrf_token(); - $expected = << - - + $expected = <<<'EOH' + + + - EOH; - } else { - $expected = <<<'EOH' - + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $hidden = [ + 'foo' => 'bar', + ]; + $this->assertSame($expected, form_open('foo/bar', $attributes, $hidden)); + } - + public function testFormOpenWithHiddenWithCSRF(): void + { + $this->setRequest(); + $this->setCsrfFilter(); - EOH; - } + $Value = csrf_hash(); + $Name = csrf_token(); + $expected = << + + + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', @@ -201,21 +230,33 @@ public function testFormOpenMultipart(): void { $this->setRequest(); - $before = (new Filters())->globals['before']; - if (in_array('csrf', $before, true) || array_key_exists('csrf', $before)) { - $Value = csrf_hash(); - $Name = csrf_token(); - $expected = << - - - EOH; - } else { - $expected = <<<'EOH' - - - EOH; - } + $expected = <<<'EOH' + + + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $this->assertSame($expected, form_open_multipart('foo/bar', $attributes)); + + // make sure it works with attributes as a string too + $attributesString = 'name="form" id="form" method="POST"'; + $this->assertSame($expected, form_open_multipart('foo/bar', $attributesString)); + } + + public function testFormOpenMultipartWithCSRF(): void + { + $this->setRequest(); + $this->setCsrfFilter(); + + $Value = csrf_hash(); + $Name = csrf_token(); + $expected = << + + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', From 7e03d7f8a2c62cb693ccbba1d0a5fdfe382511c2 Mon Sep 17 00:00:00 2001 From: kenjis Date: Tue, 9 Apr 2024 07:02:29 +0900 Subject: [PATCH 40/92] test: fix test method names MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It was difficult to read with --testdox E.g., ✔ Form open without action with c s r f --- tests/system/Helpers/FormHelperTest.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php index c139f263d837..31afd67bc464 100644 --- a/tests/system/Helpers/FormHelperTest.php +++ b/tests/system/Helpers/FormHelperTest.php @@ -75,7 +75,7 @@ public function testFormOpenBasic(): void $this->assertSame($expected, form_open('foo/bar', $attributes)); } - public function testFormOpenBasicWithCSRF(): void + public function testFormOpenBasicWithCsrf(): void { $this->setRequest(); $this->setCsrfFilter(); @@ -128,7 +128,7 @@ public function testFormOpenWithoutAction(): void $this->assertSame($expected, form_open('', $attributes)); } - public function testFormOpenWithoutActionWithCSRF(): void + public function testFormOpenWithoutActionWithCsrf(): void { $this->setRequest(); $this->setCsrfFilter(); @@ -163,7 +163,7 @@ public function testFormOpenWithoutMethod(): void $this->assertSame($expected, form_open('foo/bar', $attributes)); } - public function testFormOpenWithoutMethodWithCSRF(): void + public function testFormOpenWithoutMethodWithCsrf(): void { $this->setRequest(); $this->setCsrfFilter(); @@ -202,7 +202,7 @@ public function testFormOpenWithHidden(): void $this->assertSame($expected, form_open('foo/bar', $attributes, $hidden)); } - public function testFormOpenWithHiddenWithCSRF(): void + public function testFormOpenWithHiddenWithCsrf(): void { $this->setRequest(); $this->setCsrfFilter(); @@ -246,7 +246,7 @@ public function testFormOpenMultipart(): void $this->assertSame($expected, form_open_multipart('foo/bar', $attributesString)); } - public function testFormOpenMultipartWithCSRF(): void + public function testFormOpenMultipartWithCsrf(): void { $this->setRequest(); $this->setCsrfFilter(); @@ -320,7 +320,7 @@ public function testFormInput(): void $this->assertSame($expected, form_input($data)); } - public function testFormInputXHTML(): void + public function testFormInputXhtml(): void { $this->disableHtml5(); @@ -385,7 +385,7 @@ public function testFormUpload(): void $this->assertSame($expected, form_upload('attachment')); } - public function testFormUploadXHTML(): void + public function testFormUploadXhtml(): void { $this->disableHtml5(); @@ -721,7 +721,7 @@ public function testFormCheckbox(): void $this->assertSame($expected, form_checkbox('newsletter', 'accept', true)); } - public function testFormCheckboxXHTML(): void + public function testFormCheckboxXhtml(): void { $this->disableHtml5(); From a45342a10f39ffb7d70bbdf31d3bee910d0e78b1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 10:50:06 +0900 Subject: [PATCH 41/92] test: rename variable names Should be lc first. --- tests/system/Helpers/FormHelperTest.php | 30 ++++++++++++------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/tests/system/Helpers/FormHelperTest.php b/tests/system/Helpers/FormHelperTest.php index 31afd67bc464..b623068943fe 100644 --- a/tests/system/Helpers/FormHelperTest.php +++ b/tests/system/Helpers/FormHelperTest.php @@ -80,11 +80,11 @@ public function testFormOpenBasicWithCsrf(): void $this->setRequest(); $this->setCsrfFilter(); - $Value = csrf_hash(); - $Name = csrf_token(); + $value = csrf_hash(); + $name = csrf_token(); $expected = << - + EOH; $attributes = [ @@ -133,11 +133,11 @@ public function testFormOpenWithoutActionWithCsrf(): void $this->setRequest(); $this->setCsrfFilter(); - $Value = csrf_hash(); - $Name = csrf_token(); + $value = csrf_hash(); + $name = csrf_token(); $expected = << - + EOH; $attributes = [ 'name' => 'form', @@ -168,11 +168,11 @@ public function testFormOpenWithoutMethodWithCsrf(): void $this->setRequest(); $this->setCsrfFilter(); - $Value = csrf_hash(); - $Name = csrf_token(); + $value = csrf_hash(); + $name = csrf_token(); $expected = << - + EOH; $attributes = [ 'name' => 'form', @@ -207,11 +207,11 @@ public function testFormOpenWithHiddenWithCsrf(): void $this->setRequest(); $this->setCsrfFilter(); - $Value = csrf_hash(); - $Name = csrf_token(); + $value = csrf_hash(); + $name = csrf_token(); $expected = << - + EOH; @@ -251,11 +251,11 @@ public function testFormOpenMultipartWithCsrf(): void $this->setRequest(); $this->setCsrfFilter(); - $Value = csrf_hash(); - $Name = csrf_token(); + $value = csrf_hash(); + $name = csrf_token(); $expected = << - + EOH; $attributes = [ 'name' => 'form', From b936fcc387e2f8f2f829f8a110429101c03b2b41 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 16:41:48 +0900 Subject: [PATCH 42/92] fix: CURLRequest has multiple headers for Content-Type --- system/HTTP/CURLRequest.php | 5 +++- .../HTTP/CURLRequestDoNotShareOptionsTest.php | 23 ++++++++++++++++--- tests/system/HTTP/CURLRequestTest.php | 6 ++--- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 725195918209..4d6529eedb14 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -116,7 +116,10 @@ public function __construct(App $config, URI $uri, ?ResponseInterface $response parent::__construct(Method::GET, $uri); - $this->responseOrig = $response ?? new Response(config(App::class)); + $this->responseOrig = $response ?? new Response(config(App::class)); + // Remove the default Content-Type header. + $this->responseOrig->removeHeader('Content-Type'); + $this->baseURI = $uri->useRawQueryString(); $this->defaultOptions = $options; diff --git a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php index 1adea4d7d106..5469a2bc2fea 100644 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php @@ -784,7 +784,6 @@ public function testSendContinuedWithManyHeaders(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Server', 'Connection', 'Keep-Alive', @@ -792,6 +791,7 @@ public function testSendContinuedWithManyHeaders(): void 'Date', 'Expires', 'Pragma', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -823,10 +823,10 @@ public function testResponseHeadersWithMultipleRequests(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Server', 'Expires', 'Pragma', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -846,8 +846,8 @@ public function testResponseHeadersWithMultipleRequests(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Expires', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -1141,4 +1141,21 @@ public function testUserAgentOption(): void $this->assertArrayHasKey(CURLOPT_USERAGENT, $options); $this->assertSame($agent, $options[CURLOPT_USERAGENT]); } + + public function testGetHeaderLineContentType(): void + { + $output = 'HTTP/2 200 +date: Thu, 11 Apr 2024 07:26:00 GMT +content-type: text/html; charset=UTF-8 +cache-control: no-store, max-age=0, no-cache +server: cloudflare +content-encoding: br +alt-svc: h3=":443"; ma=86400' . "\x0d\x0a\x0d\x0aResponse Body"; + + $this->request->setOutput($output); + + $response = $this->request->request('get', 'http://example.com'); + + $this->assertSame('text/html; charset=UTF-8', $response->getHeaderLine('Content-Type')); + } } diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 7bcabaf3f986..0c170f7e5164 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -782,7 +782,6 @@ public function testSendContinuedWithManyHeaders(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Server', 'Connection', 'Keep-Alive', @@ -790,6 +789,7 @@ public function testSendContinuedWithManyHeaders(): void 'Date', 'Expires', 'Pragma', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -836,10 +836,10 @@ public function testResponseHeadersWithMultipleRequests(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Server', 'Expires', 'Pragma', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -859,8 +859,8 @@ public function testResponseHeadersWithMultipleRequests(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Expires', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); From 9ba3fea7c4e2e283276e1e532ab76524d3ef5891 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 16:34:02 +0900 Subject: [PATCH 43/92] test: fix incorrect sample HTTP responses --- .../HTTP/CURLRequestDoNotShareOptionsTest.php | 56 +++++++++---------- tests/system/HTTP/CURLRequestTest.php | 56 +++++++++---------- 2 files changed, 56 insertions(+), 56 deletions(-) diff --git a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php index 5469a2bc2fea..7b5ad56dba0e 100644 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php @@ -404,20 +404,20 @@ public function testAuthBasicOptionExplicit(): void public function testAuthDigestOption(): void { $output = "HTTP/1.1 401 Unauthorized - Server: ddos-guard - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK - Server: ddos-guard - Connection: keep-alive - Keep-Alive: timeout=60 - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - Date: Tue, 07 Jul 2020 15:13:14 GMT - Expires: Thu, 19 Nov 1981 08:52:00 GMT - Cache-Control: no-store, no-cache, must-revalidate - Pragma: no-cache - Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ - Content-Type: application/xml; charset=utf-8 - Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; +Server: ddos-guard +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK +Server: ddos-guard +Connection: keep-alive +Keep-Alive: timeout=60 +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +Date: Tue, 07 Jul 2020 15:13:14 GMT +Expires: Thu, 19 Nov 1981 08:52:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Pragma: no-cache +Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ +Content-Type: application/xml; charset=utf-8 +Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; $this->request->setOutput($output); @@ -457,20 +457,20 @@ public function testSetAuthBasic(): void public function testSetAuthDigest(): void { $output = "HTTP/1.1 401 Unauthorized - Server: ddos-guard - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK - Server: ddos-guard - Connection: keep-alive - Keep-Alive: timeout=60 - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - Date: Tue, 07 Jul 2020 15:13:14 GMT - Expires: Thu, 19 Nov 1981 08:52:00 GMT - Cache-Control: no-store, no-cache, must-revalidate - Pragma: no-cache - Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ - Content-Type: application/xml; charset=utf-8 - Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; +Server: ddos-guard +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK +Server: ddos-guard +Connection: keep-alive +Keep-Alive: timeout=60 +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +Date: Tue, 07 Jul 2020 15:13:14 GMT +Expires: Thu, 19 Nov 1981 08:52:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Pragma: no-cache +Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ +Content-Type: application/xml; charset=utf-8 +Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; $this->request->setOutput($output); diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 0c170f7e5164..99c2f65fbac7 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -387,20 +387,20 @@ public function testAuthBasicOptionExplicit(): void public function testAuthDigestOption(): void { $output = "HTTP/1.1 401 Unauthorized - Server: ddos-guard - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK - Server: ddos-guard - Connection: keep-alive - Keep-Alive: timeout=60 - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - Date: Tue, 07 Jul 2020 15:13:14 GMT - Expires: Thu, 19 Nov 1981 08:52:00 GMT - Cache-Control: no-store, no-cache, must-revalidate - Pragma: no-cache - Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ - Content-Type: application/xml; charset=utf-8 - Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; +Server: ddos-guard +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK +Server: ddos-guard +Connection: keep-alive +Keep-Alive: timeout=60 +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +Date: Tue, 07 Jul 2020 15:13:14 GMT +Expires: Thu, 19 Nov 1981 08:52:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Pragma: no-cache +Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ +Content-Type: application/xml; charset=utf-8 +Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; $this->request->setOutput($output); @@ -440,20 +440,20 @@ public function testSetAuthBasic(): void public function testSetAuthDigest(): void { $output = "HTTP/1.1 401 Unauthorized - Server: ddos-guard - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK - Server: ddos-guard - Connection: keep-alive - Keep-Alive: timeout=60 - Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT - Date: Tue, 07 Jul 2020 15:13:14 GMT - Expires: Thu, 19 Nov 1981 08:52:00 GMT - Cache-Control: no-store, no-cache, must-revalidate - Pragma: no-cache - Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ - Content-Type: application/xml; charset=utf-8 - Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; +Server: ddos-guard +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK +Server: ddos-guard +Connection: keep-alive +Keep-Alive: timeout=60 +Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT +Date: Tue, 07 Jul 2020 15:13:14 GMT +Expires: Thu, 19 Nov 1981 08:52:00 GMT +Cache-Control: no-store, no-cache, must-revalidate +Pragma: no-cache +Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ +Content-Type: application/xml; charset=utf-8 +Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; $this->request->setOutput($output); From 7a552d3708b0d952c9c5e47329b328748404d13e Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 16:56:44 +0900 Subject: [PATCH 44/92] test: fix incorrect type definition --- phpstan-baseline.php | 15 --------------- .../HTTP/CURLRequestDoNotShareOptionsTest.php | 4 ++-- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index a49319ffd2f8..4a614d93e7b2 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -12906,11 +12906,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/CLIRequestTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Access to an undefined property CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:\\$curl_options\\.$#', - 'count' => 39, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Assigning \'10\' directly on offset \'HTTP_CONTENT_LENGTH\' of \\$_SERVER is discouraged\\.$#', 'count' => 1, @@ -12931,16 +12926,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Call to an undefined method CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:setOutput\\(\\)\\.$#', - 'count' => 3, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestDoNotShareOptionsTest\\:\\:getRequest\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestDoNotShareOptionsTest\\:\\:getRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', 'count' => 1, diff --git a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php index 7b5ad56dba0e..54de1004fb68 100644 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php @@ -29,7 +29,7 @@ */ final class CURLRequestDoNotShareOptionsTest extends CIUnitTestCase { - private CURLRequest $request; + private MockCURLRequest $request; protected function setUp(): void { @@ -39,7 +39,7 @@ protected function setUp(): void $this->request = $this->getRequest(); } - protected function getRequest(array $options = []) + protected function getRequest(array $options = []): MockCURLRequest { $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); $app = new App(); From f06002ededfe216aa907e62c5409528f524e6a67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F?= Date: Thu, 11 Apr 2024 19:31:35 +0300 Subject: [PATCH 45/92] Update system/View/Plugins.php Co-authored-by: kenjis --- system/View/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index 699aa3f61a59..1a7b33f26a0e 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -43,7 +43,7 @@ public static function previousURL() /** * Wrap helper function to use as view plugin. * - * @param array{uri?: string, title?: string, attributes?: string} $params + * @param array{email?: string, title?: string, attributes?: array|object|string} $params */ public static function mailto(array $params = []): string { From b3caaf92122ef831f8041b728e5f5079aabb5b6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F?= Date: Thu, 11 Apr 2024 19:32:04 +0300 Subject: [PATCH 46/92] Update system/View/Plugins.php Co-authored-by: kenjis --- system/View/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index 1a7b33f26a0e..ba5688baa1a5 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -57,7 +57,7 @@ public static function mailto(array $params = []): string /** * Wrap helper function to use as view plugin. * - * @param array{email?: string, title?: string, attributes?: string} $params + * @param array{email?: string, title?: string, attributes?: array|object|string} $params */ public static function safeMailto(array $params = []): string { From feca8b508051aa9890f6e5d851aaae687e539b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F?= Date: Thu, 11 Apr 2024 19:33:37 +0300 Subject: [PATCH 47/92] Update system/View/Plugins.php Co-authored-by: kenjis --- system/View/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index ba5688baa1a5..96c27f96db0c 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -71,7 +71,7 @@ public static function safeMailto(array $params = []): string /** * Wrap helper function to use as view plugin. * - * @param list $params + * @param array|list $params */ public static function lang(array $params = []): string { From 44225040766512497c266401fad4cf8acb669266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F?= Date: Thu, 11 Apr 2024 19:48:24 +0300 Subject: [PATCH 48/92] Update system/View/Plugins.php Co-authored-by: kenjis --- system/View/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index 96c27f96db0c..99288ee5c52e 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -110,7 +110,7 @@ public static function route(array $params = []) /** * Wrap helper function to use as view plugin. * - * @param array{uri?: string, title?: string, attributes?: string} $params + * @param list $params */ public static function siteURL(array $params = []): string { From 70348680cf6560123b6990e4f941c5bdcb9d4950 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F?= Date: Thu, 11 Apr 2024 19:48:29 +0300 Subject: [PATCH 49/92] Update system/View/Plugins.php Co-authored-by: kenjis --- system/View/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index 99288ee5c52e..19b431a0fab3 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -98,7 +98,7 @@ public static function ValidationErrors(array $params = []): string /** * Wrap helper function to use as view plugin. * - * @param list $params + * @param list $params * * @return false|string */ From 8e396474715db0e9fe23d146061395d99d52a948 Mon Sep 17 00:00:00 2001 From: obozdag Date: Thu, 11 Apr 2024 22:59:40 +0200 Subject: [PATCH 50/92] docs: Update routing.rst Updated the explanation under "Array Callable Syntax" header. --- user_guide_src/source/incoming/routing.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 77da04253bff..134b0e248134 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -122,8 +122,7 @@ Or using ``use`` keyword: :lines: 2- If you forget to add ``use App\Controllers\Home;``, the controller classname is -interpreted as ``Config\Home``, not ``App\Controllers\Home`` because -**app/Config/Routes.php** has ``namespace Config;`` at the top. +interpreted as ``\Home``, not ``App\Controllers\Home``. .. note:: When you use Array Callable Syntax, the classname is always interpreted as a fully qualified classname. So :ref:`routing-default-namespace` and From 631f9ab0f09fab909a0f6e88ad3952cf26f3b2ab Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 16:51:07 +0900 Subject: [PATCH 51/92] fix: construct param $config is not used The construct param should be used. --- phpstan-baseline.php | 5 ----- system/HTTP/CURLRequest.php | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 4a614d93e7b2..61841f81795a 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -5336,11 +5336,6 @@ 'count' => 10, 'path' => __DIR__ . '/system/HTTP/CURLRequest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Constructor of class CodeIgniter\\\\HTTP\\\\CURLRequest has an unused parameter \\$config\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/HTTP/CURLRequest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:__construct\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', 'count' => 1, diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 4d6529eedb14..3040f29b9feb 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -116,7 +116,7 @@ public function __construct(App $config, URI $uri, ?ResponseInterface $response parent::__construct(Method::GET, $uri); - $this->responseOrig = $response ?? new Response(config(App::class)); + $this->responseOrig = $response ?? new Response($config); // Remove the default Content-Type header. $this->responseOrig->removeHeader('Content-Type'); From b63176ee0f51e9561a06b03f0f2e25c79d56e1b9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 11:02:31 +0900 Subject: [PATCH 52/92] docs: add links to change log --- user_guide_src/source/installation/installing_composer.rst | 6 ++++-- user_guide_src/source/installation/installing_manual.rst | 3 ++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index 7096c3d6fb73..10cfaf6fc8ed 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -82,7 +82,8 @@ Whenever there is a new release, then from the command line in your project root composer update -Read the :doc:`upgrade instructions `, and check Breaking Changes and Enhancements. +Read the :doc:`upgrade instructions ` and :doc:`change log <../changelogs/index>`, +and check Breaking Changes and Enhancements. Pros ---- @@ -215,7 +216,8 @@ Whenever there is a new release, then from the command line in your project root composer update -Read the :doc:`upgrade instructions `, and check Breaking Changes and Enhancements. +Read the :doc:`upgrade instructions ` and :doc:`change log <../changelogs/index>`, +and check Breaking Changes and Enhancements. Pros ---- diff --git a/user_guide_src/source/installation/installing_manual.rst b/user_guide_src/source/installation/installing_manual.rst index 8b55e375de0b..150c42ee98a1 100644 --- a/user_guide_src/source/installation/installing_manual.rst +++ b/user_guide_src/source/installation/installing_manual.rst @@ -42,7 +42,8 @@ Upgrading Download a new copy of the framework, and then replace the **system** folder. -Read the :doc:`upgrade instructions `, and check Breaking Changes and Enhancements. +Read the :doc:`upgrade instructions ` and :doc:`change log <../changelogs/index>`, +and check Breaking Changes and Enhancements. Pros ==== From 91e0861f1d05fe92ad78d17af6e9453bc347f4cc Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 11:13:48 +0900 Subject: [PATCH 53/92] docs: add sub section "Upgrading to a Specified Version" --- .../installation/installing_composer.rst | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index 10cfaf6fc8ed..2303011bb47f 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -85,6 +85,23 @@ Whenever there is a new release, then from the command line in your project root Read the :doc:`upgrade instructions ` and :doc:`change log <../changelogs/index>`, and check Breaking Changes and Enhancements. +Upgrading to a Specified Version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, you may want to upgrade to v4.4.8 after v4.5.0 has been released. + +In that case, open **composer.json** in your project root folder, and specify +the framework version: + +.. code-block:: text + + "require": { + ... + "codeigniter4/framework": "4.4.8" + }, + +Then, run the ``composer update`` command. + Pros ---- @@ -219,6 +236,23 @@ Whenever there is a new release, then from the command line in your project root Read the :doc:`upgrade instructions ` and :doc:`change log <../changelogs/index>`, and check Breaking Changes and Enhancements. +Upgrading to a Specified Version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, you may want to upgrade to v4.4.8 after v4.5.0 has been released. + +In that case, open **composer.json** in your project root folder, and specify +the framework version: + +.. code-block:: text + + "require": { + ... + "codeigniter4/framework": "4.4.8" + }, + +Then, run the ``composer update`` command. + Pros ---- From da8a486b9cb2b1b17945c010a408562caa72971f Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 07:57:46 +0900 Subject: [PATCH 54/92] docs: fix by proofreading Co-authored-by: Michal Sniatala --- user_guide_src/source/installation/installing_composer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index 2303011bb47f..eadbb3f72cde 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -88,7 +88,7 @@ and check Breaking Changes and Enhancements. Upgrading to a Specified Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, you may want to upgrade to v4.4.8 after v4.5.0 has been released. +For example, you may want to upgrade from v4.4.7 to v4.4.8 after v4.5.0 has been released. In that case, open **composer.json** in your project root folder, and specify the framework version: From 42c8ad5224b7cdc4daa2849f2f962d306a2e181e Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 08:13:42 +0900 Subject: [PATCH 55/92] docs: add section "Installing Previous Versions" and note --- .../installation/installing_composer.rst | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index eadbb3f72cde..557f81e8d5b8 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -65,6 +65,35 @@ If you omit the "project-root" argument, the command will create an that are not needed in the production environment. This will greatly reduce the vendor folder size. +Installing Previous Versions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, you may want to install v4.4.8 after v4.5.0 has been released. + +In that case, specify the version in the command: + +.. code-block:: console + + composer create-project codeigniter4/appstarter:4.4.8 project-root + +Then, open **composer.json** in your project root folder, and specify +the framework version: + +.. code-block:: text + + "require": { + ... + "codeigniter4/framework": "4.4.8" + }, + +Then, run the ``composer update`` command. + +.. note:: If you fix the version number like ``"codeigniter4/framework": "4.4.8"`` + in your **composer.json**, ``composer update`` command will not update the + framework. See `Writing Version Constraints`_ for how to specify the version. + +.. _Writing Version Constraints: https://getcomposer.org/doc/articles/versions.md#writing-version-constraints + Initial Configuration --------------------- @@ -102,6 +131,10 @@ the framework version: Then, run the ``composer update`` command. +.. note:: If you fix the version number like ``"codeigniter4/framework": "4.4.8"`` + in your **composer.json**, ``composer update`` command will not update the + framework. See `Writing Version Constraints`_ for how to specify the version. + Pros ---- From a1d45c17e7806af45cfdc43b5726cece8ced31bb Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 09:24:24 +0900 Subject: [PATCH 56/92] refactor: improve error message --- system/Debug/BaseExceptionHandler.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/system/Debug/BaseExceptionHandler.php b/system/Debug/BaseExceptionHandler.php index dbccdcd07790..4305265d2d2c 100644 --- a/system/Debug/BaseExceptionHandler.php +++ b/system/Debug/BaseExceptionHandler.php @@ -245,8 +245,14 @@ protected static function highlightFile(string $file, int $lineNumber, int $line */ protected function render(Throwable $exception, int $statusCode, $viewFile = null): void { - if (empty($viewFile) || ! is_file($viewFile)) { - echo 'The error view files were not found. Cannot render exception trace.'; + if ($viewFile === null) { + echo 'The error view file was not specified. Cannot display error view.'; + + exit(1); + } + + if (! is_file($viewFile)) { + echo 'The error view file "' . $viewFile . '" was not found. Cannot display error view.'; exit(1); } From cd6b587397d173d69eefb070ff03f871bd1baee7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 09:31:24 +0900 Subject: [PATCH 57/92] chore: update phpstan-baseline --- phpstan-baseline.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 4a614d93e7b2..a2cbffd050d0 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -4121,11 +4121,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Database/Seeder.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Debug/BaseExceptionHandler.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Debug\\\\BaseExceptionHandler\\:\\:collectVars\\(\\) return type has no value type specified in iterable type array\\.$#', 'count' => 1, From 5f35f88144ac990f9b062d9b313f3b1a6c2bc518 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 17:33:05 +0900 Subject: [PATCH 58/92] test: sync two test cases But not exactly the same. --- .../HTTP/CURLRequestDoNotShareOptionsTest.php | 71 ++++++++++++++++++- tests/system/HTTP/CURLRequestTest.php | 67 +++++++++++++++-- 2 files changed, 132 insertions(+), 6 deletions(-) diff --git a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php index 54de1004fb68..7e8afeb6b74b 100644 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php @@ -35,7 +35,7 @@ protected function setUp(): void { parent::setUp(); - Services::reset(); + $this->resetServices(); $this->request = $this->getRequest(); } @@ -552,6 +552,21 @@ public function testSSLVerification(): void $this->assertSame(2, $options[CURLOPT_SSL_VERIFYHOST]); } + public function testNoSSL(): void + { + $this->request->request('get', 'http://example.com', [ + 'verify' => false, + ]); + + $options = $this->request->curl_options; + + $this->assertArrayHasKey(CURLOPT_SSL_VERIFYPEER, $options); + $this->assertFalse($options[CURLOPT_SSL_VERIFYPEER]); + + $this->assertArrayHasKey(CURLOPT_SSL_VERIFYHOST, $options); + $this->assertSame(0, $options[CURLOPT_SSL_VERIFYHOST]); + } + public function testSSLWithBadKey(): void { $file = 'something_obviously_bogus'; @@ -799,6 +814,21 @@ public function testSendContinuedWithManyHeaders(): void $this->assertSame(200, $response->getStatusCode()); } + public function testSendProxied(): void + { + $request = $this->getRequest([ + 'base_uri' => 'http://www.foo.com/api/v1/', + 'delay' => 100, + ]); + + $output = "HTTP/1.1 200 Connection established +Proxy-Agent: Fortinet-Proxy/1.0\x0d\x0a\x0d\x0aHTTP/1.1 200 OK\x0d\x0a\x0d\x0aHi there"; + $request->setOutput($output); + + $response = $request->get('answer'); + $this->assertSame('Hi there', $response->getBody()); + } + /** * See: https://github.com/codeigniter4/CodeIgniter4/issues/7394 */ @@ -1082,7 +1112,6 @@ public function testSetJSON(): void $expected, $this->request->curl_options[CURLOPT_POSTFIELDS] ); - $this->assertSame( 'Content-Type: application/json', $this->request->curl_options[CURLOPT_HTTPHEADER][0] @@ -1113,6 +1142,18 @@ public function testHTTPv11(): void $this->assertSame(CURL_HTTP_VERSION_1_1, $options[CURLOPT_HTTP_VERSION]); } + public function testHTTPv2(): void + { + $this->request->request('POST', '/post', [ + 'version' => 2.0, + ]); + + $options = $this->request->curl_options; + + $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); + $this->assertSame(CURL_HTTP_VERSION_2_0, $options[CURLOPT_HTTP_VERSION]); + } + public function testCookieOption(): void { $holder = SUPPORTPATH . 'HTTP/Files/CookiesHolder.txt'; @@ -1142,6 +1183,32 @@ public function testUserAgentOption(): void $this->assertSame($agent, $options[CURLOPT_USERAGENT]); } + /** + * @see https://github.com/codeigniter4/CodeIgniter4/issues/8347 + */ + public function testMultipleHTTP100(): void + { + $jsonBody = '{"name":"John Doe","age":30}'; + + $output = "HTTP/1.1 100 Continue +Mark bundle as not supporting multiuse +HTTP/1.1 100 Continue +Mark bundle as not supporting multiuse +HTTP/1.1 200 OK +Server: Werkzeug/2.2.2 Python/3.7.17 +Date: Sun, 28 Jan 2024 06:05:36 GMT +Content-Type: application/json +Content-Length: 33\r\n\r\n" . $jsonBody; + + $this->request->setOutput($output); + + $response = $this->request->request('GET', 'http://example.com'); + + $this->assertSame($jsonBody, $response->getBody()); + + $this->assertSame(200, $response->getStatusCode()); + } + public function testGetHeaderLineContentType(): void { $output = 'HTTP/2 200 diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 99c2f65fbac7..6657eb05c6c8 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -29,7 +29,7 @@ */ final class CURLRequestTest extends CIUnitTestCase { - private CURLRequest $request; + private MockCURLRequest $request; protected function setUp(): void { @@ -39,7 +39,7 @@ protected function setUp(): void $this->request = $this->getRequest(); } - protected function getRequest(array $options = []) + protected function getRequest(array $options = []): MockCURLRequest { $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); $app = new App(); @@ -205,7 +205,7 @@ public function testOptionsHeadersNotUsingPopulate(): void $this->assertSame('', $request->header('Accept-Encoding')->getValue()); } - public function testOptionsAreSharedBetweenRequests(): void + public function testDefaultOptionsAreSharedBetweenRequests(): void { $options = [ 'form_params' => ['studio' => 1], @@ -868,6 +868,38 @@ public function testResponseHeadersWithMultipleRequests(): void $this->assertSame(200, $response->getStatusCode()); } + public function testResponseHeadersWithMultipleSetCookies(): void + { + $request = $this->getRequest([ + 'base_uri' => 'https://github.com/', + ]); + + $output = "HTTP/2 200 +server: GitHub.com +date: Sat, 11 Nov 2023 02:26:55 GMT +content-type: text/html; charset=utf-8 +set-cookie: _gh_sess=PlRlha1YumlLhLuo5MuNbIWJRO9RRuR%2FHfYsWRh5B0mkalFIZstlAbTmSstl8q%2FAC57IsWMVuFHWQc6L4qDHQJrwhuYVO5ZaigPCUjAStnhh%2FieZQVqIf92Al7vusuzx2o8XH%2Fv6nd9qzMTAWc2%2FkRsl8jxPQYGNaWeuUBY2w3%2FDORSikN4c0vHOyedhU7Xcv3Ryz5xD3DNxK9R8xKNZ6OSXLJ6bjX8iIT6LxvroVIf2HjvowW9cQsq0kN08mS6KtTnH0mD3ANWqsVVWeMzFNA%3D%3D--Jx830Q9Nmkfz9OGA--kEcPtNphvjNMopYqFDxUbw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax +set-cookie: _octo=GH1.1.599292127.1699669625; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; Secure; SameSite=Lax +set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; HttpOnly; Secure; SameSite=Lax +accept-ranges: bytes\x0d\x0a\x0d\x0a"; + $request->setOutput($output); + + $response = $request->get('/'); + + $setCookieHeaders = $response->header('set-cookie'); + + $this->assertCount(3, $setCookieHeaders); + $this->assertSame( + 'logged_in=no; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; HttpOnly; Secure; SameSite=Lax', + $setCookieHeaders[2]->getValue() + ); + + $this->assertSame( + '_octo=GH1.1.599292127.1699669625; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; Secure; SameSite=Lax', + $setCookieHeaders[1]->getValueLine() + ); + } + public function testSplitResponse(): void { $request = $this->getRequest([ @@ -1026,6 +1058,10 @@ public function testJSONData(): void $this->assertSame('POST', $this->request->getMethod()); $expected = json_encode($params); + $this->assertSame( + $expected, + $this->request->curl_options[CURLOPT_POSTFIELDS] + ); $this->assertSame($expected, $this->request->getBody()); } @@ -1040,7 +1076,13 @@ public function testSetJSON(): void ]; $this->request->setJSON($params)->post('/post'); - $this->assertSame(json_encode($params), $this->request->getBody()); + $expected = json_encode($params); + $this->assertSame( + $expected, + $this->request->curl_options[CURLOPT_POSTFIELDS] + ); + $this->assertSame($expected, $this->request->getBody()); + $this->assertSame( 'Content-Type: application/json', $this->request->curl_options[CURLOPT_HTTPHEADER][0] @@ -1137,4 +1179,21 @@ public function testMultipleHTTP100(): void $this->assertSame(200, $response->getStatusCode()); } + + public function testGetHeaderLineContentType(): void + { + $output = 'HTTP/2 200 +date: Thu, 11 Apr 2024 07:26:00 GMT +content-type: text/html; charset=UTF-8 +cache-control: no-store, max-age=0, no-cache +server: cloudflare +content-encoding: br +alt-svc: h3=":443"; ma=86400' . "\x0d\x0a\x0d\x0aResponse Body"; + + $this->request->setOutput($output); + + $response = $this->request->request('get', 'http://example.com'); + + $this->assertSame('text/html; charset=UTF-8', $response->getHeaderLine('Content-Type')); + } } From 110798b9f9d40487963a4b1ab02f0e60c35470ec Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 17:42:34 +0900 Subject: [PATCH 59/92] test: replace test class names CURLRequestTest is the main file. --- ...st.php => CURLRequestShareOptionsTest.php} | 42 ++++--------------- tests/system/HTTP/CURLRequestTest.php | 37 ++++++++++++++-- 2 files changed, 41 insertions(+), 38 deletions(-) rename tests/system/HTTP/{CURLRequestDoNotShareOptionsTest.php => CURLRequestShareOptionsTest.php} (97%) diff --git a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php b/tests/system/HTTP/CURLRequestShareOptionsTest.php similarity index 97% rename from tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php rename to tests/system/HTTP/CURLRequestShareOptionsTest.php index 7e8afeb6b74b..b4e3cb447967 100644 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestShareOptionsTest.php @@ -23,11 +23,14 @@ use CURLFile; /** + * This test case is for the case where shareOptions is true. + * The shareOptions should be set to false. + * * @internal * * @group Others */ -final class CURLRequestDoNotShareOptionsTest extends CIUnitTestCase +final class CURLRequestShareOptionsTest extends CIUnitTestCase { private MockCURLRequest $request; @@ -45,7 +48,7 @@ protected function getRequest(array $options = []): MockCURLRequest $app = new App(); $config = new ConfigCURLRequest(); - $config->shareOptions = false; + $config->shareOptions = true; Factories::injectMock('config', 'CURLRequest', $config); return new MockCURLRequest(($app), $uri, new Response($app), $options); @@ -226,23 +229,6 @@ public function testDefaultOptionsAreSharedBetweenRequests(): void $this->assertSame('CodeIgniter Framework v4', $request->curl_options[CURLOPT_USERAGENT]); } - public function testHeaderContentLengthNotSharedBetweenRequests(): void - { - $options = [ - 'base_uri' => 'http://www.foo.com/api/v1/', - ]; - $request = $this->getRequest($options); - - $request->post('example', [ - 'form_params' => [ - 'q' => 'keyword', - ], - ]); - $request->get('example'); - - $this->assertNull($request->header('Content-Length')); - } - /** * @backupGlobals enabled */ @@ -960,21 +946,6 @@ public function testApplyBodyByOptions(): void $this->assertSame('name=George', $request->curl_options[CURLOPT_POSTFIELDS]); } - public function testBodyIsResetOnSecondRequest(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - $request->setBody('name=George'); - $request->setOutput('Hi there'); - - $request->post('answer'); - $request->post('answer'); - - $this->assertArrayNotHasKey(CURLOPT_POSTFIELDS, $request->curl_options); - } - public function testResponseHeaders(): void { $request = $this->getRequest([ @@ -1094,6 +1065,7 @@ public function testJSONData(): void $expected, $this->request->curl_options[CURLOPT_POSTFIELDS] ); + $this->assertSame($expected, $this->request->getBody()); } public function testSetJSON(): void @@ -1112,6 +1084,8 @@ public function testSetJSON(): void $expected, $this->request->curl_options[CURLOPT_POSTFIELDS] ); + $this->assertSame($expected, $this->request->getBody()); + $this->assertSame( 'Content-Type: application/json', $this->request->curl_options[CURLOPT_HTTPHEADER][0] diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 6657eb05c6c8..32d6a4dd919d 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -45,7 +45,7 @@ protected function getRequest(array $options = []): MockCURLRequest $app = new App(); $config = new ConfigCURLRequest(); - $config->shareOptions = true; + $config->shareOptions = false; Factories::injectMock('config', 'CURLRequest', $config); return new MockCURLRequest(($app), $uri, new Response($app), $options); @@ -226,6 +226,23 @@ public function testDefaultOptionsAreSharedBetweenRequests(): void $this->assertSame('CodeIgniter Framework v4', $request->curl_options[CURLOPT_USERAGENT]); } + public function testHeaderContentLengthNotSharedBetweenRequests(): void + { + $options = [ + 'base_uri' => 'http://www.foo.com/api/v1/', + ]; + $request = $this->getRequest($options); + + $request->post('example', [ + 'form_params' => [ + 'q' => 'keyword', + ], + ]); + $request->get('example'); + + $this->assertNull($request->header('Content-Length')); + } + /** * @backupGlobals enabled */ @@ -943,6 +960,21 @@ public function testApplyBodyByOptions(): void $this->assertSame('name=George', $request->curl_options[CURLOPT_POSTFIELDS]); } + public function testBodyIsResetOnSecondRequest(): void + { + $request = $this->getRequest([ + 'base_uri' => 'http://www.foo.com/api/v1/', + 'delay' => 100, + ]); + $request->setBody('name=George'); + $request->setOutput('Hi there'); + + $request->post('answer'); + $request->post('answer'); + + $this->assertArrayNotHasKey(CURLOPT_POSTFIELDS, $request->curl_options); + } + public function testResponseHeaders(): void { $request = $this->getRequest([ @@ -1062,7 +1094,6 @@ public function testJSONData(): void $expected, $this->request->curl_options[CURLOPT_POSTFIELDS] ); - $this->assertSame($expected, $this->request->getBody()); } public function testSetJSON(): void @@ -1081,8 +1112,6 @@ public function testSetJSON(): void $expected, $this->request->curl_options[CURLOPT_POSTFIELDS] ); - $this->assertSame($expected, $this->request->getBody()); - $this->assertSame( 'Content-Type: application/json', $this->request->curl_options[CURLOPT_HTTPHEADER][0] From 83be00a72a3d6e052704f0ec174225562179704f Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 17:50:37 +0900 Subject: [PATCH 60/92] test: refactoring with inheritance --- .../HTTP/CURLRequestShareOptionsTest.php | 1144 +---------------- tests/system/HTTP/CURLRequestTest.php | 6 +- 2 files changed, 13 insertions(+), 1137 deletions(-) diff --git a/tests/system/HTTP/CURLRequestShareOptionsTest.php b/tests/system/HTTP/CURLRequestShareOptionsTest.php index b4e3cb447967..bb0216466787 100644 --- a/tests/system/HTTP/CURLRequestShareOptionsTest.php +++ b/tests/system/HTTP/CURLRequestShareOptionsTest.php @@ -14,13 +14,9 @@ namespace CodeIgniter\HTTP; use CodeIgniter\Config\Factories; -use CodeIgniter\Config\Services; -use CodeIgniter\HTTP\Exceptions\HTTPException; -use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\Mock\MockCURLRequest; use Config\App; use Config\CURLRequest as ConfigCURLRequest; -use CURLFile; /** * This test case is for the case where shareOptions is true. @@ -30,18 +26,8 @@ * * @group Others */ -final class CURLRequestShareOptionsTest extends CIUnitTestCase +final class CURLRequestShareOptionsTest extends CURLRequestTest { - private MockCURLRequest $request; - - protected function setUp(): void - { - parent::setUp(); - - $this->resetServices(); - $this->request = $this->getRequest(); - } - protected function getRequest(array $options = []): MockCURLRequest { $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); @@ -54,1149 +40,37 @@ protected function getRequest(array $options = []): MockCURLRequest return new MockCURLRequest(($app), $uri, new Response($app), $options); } - /** - * @see https://github.com/codeigniter4/CodeIgniter4/issues/4707 - */ - public function testPrepareURLIgnoresAppConfig(): void - { - config('App')->baseURL = 'http://example.com/fruit/'; - - $request = $this->getRequest(['base_uri' => 'http://example.com/v1/']); - - $method = $this->getPrivateMethodInvoker($request, 'prepareURL'); - - $this->assertSame('http://example.com/v1/bananas', $method('bananas')); - } - - /** - * @see https://github.com/codeigniter4/CodeIgniter4/issues/1029 - */ - public function testGetRemembersBaseURI(): void - { - $request = $this->getRequest(['base_uri' => 'http://www.foo.com/api/v1/']); - - $request->get('products'); - - $options = $request->curl_options; - - $this->assertSame('http://www.foo.com/api/v1/products', $options[CURLOPT_URL]); - } - - /** - * @see https://github.com/codeigniter4/CodeIgniter4/issues/1029 - */ - public function testGetRemembersBaseURIWithHelperMethod(): void - { - $request = Services::curlrequest(['base_uri' => 'http://www.foo.com/api/v1/']); - - $uri = $this->getPrivateProperty($request, 'baseURI'); - $this->assertSame('www.foo.com', $uri->getHost()); - $this->assertSame('/api/v1/', $uri->getPath()); - } - - public function testSendReturnsResponse(): void - { - $output = 'Howdy Stranger.'; - - $response = $this->request->setOutput($output)->send('get', 'http://example.com'); - - $this->assertInstanceOf(Response::class, $response); - $this->assertSame($output, $response->getBody()); - } - - public function testGetSetsCorrectMethod(): void - { - $this->request->get('http://example.com'); - - $this->assertSame('GET', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('GET', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testDeleteSetsCorrectMethod(): void - { - $this->request->delete('http://example.com'); - - $this->assertSame('DELETE', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('DELETE', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testHeadSetsCorrectMethod(): void - { - $this->request->head('http://example.com'); - - $this->assertSame('HEAD', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('HEAD', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testOptionsSetsCorrectMethod(): void - { - $this->request->options('http://example.com'); - - $this->assertSame('OPTIONS', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('OPTIONS', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testOptionsBaseURIOption(): void - { - $options = ['base_uri' => 'http://www.foo.com/api/v1/']; - $request = $this->getRequest($options); - - $this->assertSame('http://www.foo.com/api/v1/', $request->getBaseURI()->__toString()); - } - - public function testOptionsBaseURIOverride(): void - { - $options = [ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'baseURI' => 'http://bogus/com', - ]; - $request = $this->getRequest($options); - - $this->assertSame('http://bogus/com', $request->getBaseURI()->__toString()); - } - - public function testOptionsHeaders(): void - { - $options = [ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'headers' => ['fruit' => 'apple'], - ]; - $request = $this->getRequest(); - $this->assertNull($request->header('fruit')); - - $request = $this->getRequest($options); - $this->assertSame('apple', $request->header('fruit')->getValue()); - } - - /** - * @backupGlobals enabled - */ - public function testOptionsHeadersNotUsingPopulate(): void + public function testHeaderContentLengthNotSharedBetweenRequests(): void { - $_SERVER['HTTP_HOST'] = 'site1.com'; - $_SERVER['HTTP_ACCEPT_LANGUAGE'] = 'en-US'; - $_SERVER['HTTP_ACCEPT_ENCODING'] = 'gzip, deflate, br'; - $options = [ 'base_uri' => 'http://www.foo.com/api/v1/', - 'headers' => [ - 'Host' => 'www.foo.com', - 'Accept-Encoding' => '', - ], ]; $request = $this->getRequest($options); - $request->get('example'); - // if headers for the request are defined we use them - $this->assertNull($request->header('Accept-Language')); - $this->assertSame('www.foo.com', $request->header('Host')->getValue()); - $this->assertSame('', $request->header('Accept-Encoding')->getValue()); - } - public function testDefaultOptionsAreSharedBetweenRequests(): void - { - $options = [ - 'form_params' => ['studio' => 1], - 'user_agent' => 'CodeIgniter Framework v4', - ]; - $request = $this->getRequest($options); - - $request->request('POST', 'https://realestate1.example.com'); - - $this->assertSame('https://realestate1.example.com', $request->curl_options[CURLOPT_URL]); - $this->assertSame('studio=1', $request->curl_options[CURLOPT_POSTFIELDS]); - $this->assertSame('CodeIgniter Framework v4', $request->curl_options[CURLOPT_USERAGENT]); - - $request->request('POST', 'https://realestate2.example.com'); - - $this->assertSame('https://realestate2.example.com', $request->curl_options[CURLOPT_URL]); - $this->assertSame('studio=1', $request->curl_options[CURLOPT_POSTFIELDS]); - $this->assertSame('CodeIgniter Framework v4', $request->curl_options[CURLOPT_USERAGENT]); - } - - /** - * @backupGlobals enabled - */ - public function testHeaderContentLengthNotSharedBetweenClients(): void - { - $_SERVER['HTTP_CONTENT_LENGTH'] = '10'; - - $options = [ - 'base_uri' => 'http://www.foo.com/api/v1/', - ]; - $request = $this->getRequest($options); $request->post('example', [ 'form_params' => [ 'q' => 'keyword', ], ]); - - $request = $this->getRequest($options); $request->get('example'); - $this->assertNull($request->header('Content-Length')); - } - - public function testOptionsDelay(): void - { - $request = $this->getRequest(); - $this->assertEqualsWithDelta(0.0, $request->getDelay(), PHP_FLOAT_EPSILON); - - $options = [ - 'delay' => 2000, - 'headers' => ['fruit' => 'apple'], - ]; - $request = $this->getRequest($options); - $this->assertEqualsWithDelta(2.0, $request->getDelay(), PHP_FLOAT_EPSILON); - } - - public function testPatchSetsCorrectMethod(): void - { - $this->request->patch('http://example.com'); - - $this->assertSame('PATCH', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('PATCH', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testPostSetsCorrectMethod(): void - { - $this->request->post('http://example.com'); - - $this->assertSame('POST', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('POST', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testPutSetsCorrectMethod(): void - { - $this->request->put('http://example.com'); - - $this->assertSame('PUT', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('PUT', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testCustomMethodSetsCorrectMethod(): void - { - $this->request->request('custom', 'http://example.com'); - - $this->assertSame('custom', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('custom', $options[CURLOPT_CUSTOMREQUEST]); + // The Content-Length header is shared! + $this->assertSame('9', $request->header('Content-Length')->getValue()); } - public function testRequestMethodGetsSanitized(): void - { - $this->request->request('', 'http://example.com'); - - $this->assertSame('Custom', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CUSTOMREQUEST, $options); - $this->assertSame('Custom', $options[CURLOPT_CUSTOMREQUEST]); - } - - public function testRequestSetsBasicCurlOptions(): void - { - $this->request->request('get', 'http://example.com'); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_URL, $options); - $this->assertSame('http://example.com', $options[CURLOPT_URL]); - - $this->assertArrayHasKey(CURLOPT_RETURNTRANSFER, $options); - $this->assertTrue($options[CURLOPT_RETURNTRANSFER]); - - $this->assertArrayHasKey(CURLOPT_HEADER, $options); - $this->assertTrue($options[CURLOPT_HEADER]); - - $this->assertArrayHasKey(CURLOPT_FRESH_CONNECT, $options); - $this->assertTrue($options[CURLOPT_FRESH_CONNECT]); - - $this->assertArrayHasKey(CURLOPT_TIMEOUT_MS, $options); - $this->assertEqualsWithDelta(0.0, $options[CURLOPT_TIMEOUT_MS], PHP_FLOAT_EPSILON); - - $this->assertArrayHasKey(CURLOPT_CONNECTTIMEOUT_MS, $options); - $this->assertEqualsWithDelta(150000.0, $options[CURLOPT_CONNECTTIMEOUT_MS], PHP_FLOAT_EPSILON); - } - - public function testAuthBasicOption(): void - { - $this->request->request('get', 'http://example.com', [ - 'auth' => [ - 'username', - 'password', - ], - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_USERPWD, $options); - $this->assertSame('username:password', $options[CURLOPT_USERPWD]); - - $this->assertArrayHasKey(CURLOPT_HTTPAUTH, $options); - $this->assertSame(CURLAUTH_BASIC, $options[CURLOPT_HTTPAUTH]); - } - - public function testAuthBasicOptionExplicit(): void - { - $this->request->request('get', 'http://example.com', [ - 'auth' => [ - 'username', - 'password', - 'basic', - ], - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_USERPWD, $options); - $this->assertSame('username:password', $options[CURLOPT_USERPWD]); - - $this->assertArrayHasKey(CURLOPT_HTTPAUTH, $options); - $this->assertSame(CURLAUTH_BASIC, $options[CURLOPT_HTTPAUTH]); - } - - public function testAuthDigestOption(): void - { - $output = "HTTP/1.1 401 Unauthorized -Server: ddos-guard -Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT -WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK -Server: ddos-guard -Connection: keep-alive -Keep-Alive: timeout=60 -Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT -Date: Tue, 07 Jul 2020 15:13:14 GMT -Expires: Thu, 19 Nov 1981 08:52:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Pragma: no-cache -Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ -Content-Type: application/xml; charset=utf-8 -Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; - - $this->request->setOutput($output); - - $response = $this->request->request('get', 'http://example.com', [ - 'auth' => [ - 'username', - 'password', - 'digest', - ], - ]); - - $options = $this->request->curl_options; - - $this->assertSame('Update success! config', $response->getBody()); - $this->assertSame(200, $response->getStatusCode()); - - $this->assertArrayHasKey(CURLOPT_USERPWD, $options); - $this->assertSame('username:password', $options[CURLOPT_USERPWD]); - - $this->assertArrayHasKey(CURLOPT_HTTPAUTH, $options); - $this->assertSame(CURLAUTH_DIGEST, $options[CURLOPT_HTTPAUTH]); - } - - public function testSetAuthBasic(): void - { - $this->request->setAuth('username', 'password')->get('http://example.com'); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_USERPWD, $options); - $this->assertSame('username:password', $options[CURLOPT_USERPWD]); - - $this->assertArrayHasKey(CURLOPT_HTTPAUTH, $options); - $this->assertSame(CURLAUTH_BASIC, $options[CURLOPT_HTTPAUTH]); - } - - public function testSetAuthDigest(): void - { - $output = "HTTP/1.1 401 Unauthorized -Server: ddos-guard -Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT -WWW-Authenticate: Digest\x0d\x0a\x0d\x0aHTTP/1.1 200 OK -Server: ddos-guard -Connection: keep-alive -Keep-Alive: timeout=60 -Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT -Date: Tue, 07 Jul 2020 15:13:14 GMT -Expires: Thu, 19 Nov 1981 08:52:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Pragma: no-cache -Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ -Content-Type: application/xml; charset=utf-8 -Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; - - $this->request->setOutput($output); - - $response = $this->request->setAuth('username', 'password', 'digest')->get('http://example.com'); - - $options = $this->request->curl_options; - - $this->assertSame('Update success! config', $response->getBody()); - $this->assertSame(200, $response->getStatusCode()); - - $this->assertArrayHasKey(CURLOPT_USERPWD, $options); - $this->assertSame('username:password', $options[CURLOPT_USERPWD]); - - $this->assertArrayHasKey(CURLOPT_HTTPAUTH, $options); - $this->assertSame(CURLAUTH_DIGEST, $options[CURLOPT_HTTPAUTH]); - } - - public function testCertOption(): void - { - $file = __FILE__; - - $this->request->request('get', 'http://example.com', [ - 'cert' => $file, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_SSLCERT, $options); - $this->assertSame($file, $options[CURLOPT_SSLCERT]); - } - - public function testCertOptionWithPassword(): void - { - $file = __FILE__; - - $this->request->request('get', 'http://example.com', [ - 'cert' => [ - $file, - 'password', - ], - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_SSLCERT, $options); - $this->assertSame($file, $options[CURLOPT_SSLCERT]); - - $this->assertArrayHasKey(CURLOPT_SSLCERTPASSWD, $options); - $this->assertSame('password', $options[CURLOPT_SSLCERTPASSWD]); - } - - public function testMissingCertOption(): void - { - $file = 'something_obviously_bogus'; - $this->expectException(HTTPException::class); - - $this->request->request('get', 'http://example.com', [ - 'cert' => $file, - ]); - } - - public function testSSLVerification(): void - { - $file = __FILE__; - - $this->request->request('get', 'http://example.com', [ - 'verify' => $file, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_CAINFO, $options); - $this->assertSame($file, $options[CURLOPT_CAINFO]); - - $this->assertArrayHasKey(CURLOPT_SSL_VERIFYPEER, $options); - $this->assertTrue($options[CURLOPT_SSL_VERIFYPEER]); - - $this->assertArrayHasKey(CURLOPT_SSL_VERIFYHOST, $options); - $this->assertSame(2, $options[CURLOPT_SSL_VERIFYHOST]); - } - - public function testNoSSL(): void - { - $this->request->request('get', 'http://example.com', [ - 'verify' => false, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_SSL_VERIFYPEER, $options); - $this->assertFalse($options[CURLOPT_SSL_VERIFYPEER]); - - $this->assertArrayHasKey(CURLOPT_SSL_VERIFYHOST, $options); - $this->assertSame(0, $options[CURLOPT_SSL_VERIFYHOST]); - } - - public function testSSLWithBadKey(): void - { - $file = 'something_obviously_bogus'; - $this->expectException(HTTPException::class); - - $this->request->request('get', 'http://example.com', [ - 'verify' => $file, - ]); - } - - public function testProxyuOption(): void - { - $this->request->request('get', 'http://example.com', [ - 'proxy' => 'http://localhost:3128', - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_PROXY, $options); - $this->assertSame('http://localhost:3128', $options[CURLOPT_PROXY]); - $this->assertArrayHasKey(CURLOPT_HTTPPROXYTUNNEL, $options); - $this->assertTrue($options[CURLOPT_HTTPPROXYTUNNEL]); - } - - public function testDebugOptionTrue(): void - { - $this->request->request('get', 'http://example.com', [ - 'debug' => true, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_VERBOSE, $options); - $this->assertSame(1, $options[CURLOPT_VERBOSE]); - - $this->assertArrayHasKey(CURLOPT_STDERR, $options); - $this->assertIsResource($options[CURLOPT_STDERR]); - } - - public function testDebugOptionFalse(): void - { - $this->request->request('get', 'http://example.com', [ - 'debug' => false, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayNotHasKey(CURLOPT_VERBOSE, $options); - $this->assertArrayNotHasKey(CURLOPT_STDERR, $options); - } - - public function testDebugOptionFile(): void - { - $file = SUPPORTPATH . 'Files/baker/banana.php'; - - $this->request->request('get', 'http://example.com', [ - 'debug' => $file, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_VERBOSE, $options); - $this->assertSame(1, $options[CURLOPT_VERBOSE]); - - $this->assertArrayHasKey(CURLOPT_STDERR, $options); - $this->assertIsResource($options[CURLOPT_STDERR]); - } - - public function testDecodeContent(): void - { - $this->request->setHeader('Accept-Encoding', 'cobol'); - $this->request->request('get', 'http://example.com', [ - 'decode_content' => true, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_ENCODING, $options); - $this->assertSame('cobol', $options[CURLOPT_ENCODING]); - } - - public function testDecodeContentWithoutAccept(): void - { - // $this->request->setHeader('Accept-Encoding', 'cobol'); - $this->request->request('get', 'http://example.com', [ - 'decode_content' => true, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_ENCODING, $options); - $this->assertSame('', $options[CURLOPT_ENCODING]); - $this->assertArrayHasKey(CURLOPT_HTTPHEADER, $options); - $this->assertSame('Accept-Encoding', $options[CURLOPT_HTTPHEADER]); - } - - public function testAllowRedirectsOptionFalse(): void - { - $this->request->request('get', 'http://example.com', [ - 'allow_redirects' => false, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_FOLLOWLOCATION, $options); - $this->assertSame(0, $options[CURLOPT_FOLLOWLOCATION]); - - $this->assertArrayNotHasKey(CURLOPT_MAXREDIRS, $options); - $this->assertArrayNotHasKey(CURLOPT_REDIR_PROTOCOLS, $options); - } - - public function testAllowRedirectsOptionTrue(): void - { - $this->request->request('get', 'http://example.com', [ - 'allow_redirects' => true, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_FOLLOWLOCATION, $options); - $this->assertSame(1, $options[CURLOPT_FOLLOWLOCATION]); - - $this->assertArrayHasKey(CURLOPT_MAXREDIRS, $options); - $this->assertSame(5, $options[CURLOPT_MAXREDIRS]); - $this->assertArrayHasKey(CURLOPT_REDIR_PROTOCOLS, $options); - $this->assertSame(CURLPROTO_HTTP | CURLPROTO_HTTPS, $options[CURLOPT_REDIR_PROTOCOLS]); - } - - public function testAllowRedirectsOptionDefaults(): void - { - $this->request->request('get', 'http://example.com', [ - 'allow_redirects' => true, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_FOLLOWLOCATION, $options); - $this->assertSame(1, $options[CURLOPT_FOLLOWLOCATION]); - - $this->assertArrayHasKey(CURLOPT_MAXREDIRS, $options); - $this->assertArrayHasKey(CURLOPT_REDIR_PROTOCOLS, $options); - } - - public function testAllowRedirectsArray(): void - { - $this->request->request('get', 'http://example.com', [ - 'allow_redirects' => ['max' => 2], - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_FOLLOWLOCATION, $options); - $this->assertSame(1, $options[CURLOPT_FOLLOWLOCATION]); - - $this->assertArrayHasKey(CURLOPT_MAXREDIRS, $options); - $this->assertSame(2, $options[CURLOPT_MAXREDIRS]); - } - - public function testSendWithQuery(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'query' => [ - 'name' => 'Henry', - 'd.t' => 'value', - ], - ]); - - $request->get('products'); - - $options = $request->curl_options; - - $this->assertSame('http://www.foo.com/api/v1/products?name=Henry&d.t=value', $options[CURLOPT_URL]); - } - - public function testSendWithDelay(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $request->get('products'); - - // we still need to check the code coverage to make sure this was done - $this->assertEqualsWithDelta(0.1, $request->getDelay(), PHP_FLOAT_EPSILON); - } - - public function testSendContinued(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $request->setOutput("HTTP/1.1 100 Continue\x0d\x0a\x0d\x0aHi there"); - $response = $request->get('answer'); - $this->assertSame('Hi there', $response->getBody()); - } - - /** - * See: https://github.com/codeigniter4/CodeIgniter4/issues/3261 - */ - public function testSendContinuedWithManyHeaders(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $output = "HTTP/1.1 100 Continue -Server: ddos-guard -Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT\x0d\x0a\x0d\x0aHTTP/1.1 200 OK -Server: ddos-guard -Connection: keep-alive -Keep-Alive: timeout=60 -Set-Cookie: __ddg1=z177j4mLtqzC07v0zviU; Domain=.site.ru; HttpOnly; Path=/; Expires=Wed, 07-Jul-2021 15:13:14 GMT -Date: Tue, 07 Jul 2020 15:13:14 GMT -Expires: Thu, 19 Nov 1981 08:52:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Pragma: no-cache -Set-Cookie: PHPSESSID=80pd3hlg38mvjnelpvokp9lad0; path=/ -Content-Type: application/xml; charset=utf-8 -Transfer-Encoding: chunked\x0d\x0a\x0d\x0aUpdate success! config"; - $request->setOutput($output); - - $response = $request->get('answer'); - - $this->assertSame('Update success! config', $response->getBody()); - - $responseHeaderKeys = [ - 'Cache-Control', - 'Server', - 'Connection', - 'Keep-Alive', - 'Set-Cookie', - 'Date', - 'Expires', - 'Pragma', - 'Content-Type', - 'Transfer-Encoding', - ]; - $this->assertSame($responseHeaderKeys, array_keys($response->headers())); - - $this->assertSame(200, $response->getStatusCode()); - } - - public function testSendProxied(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $output = "HTTP/1.1 200 Connection established -Proxy-Agent: Fortinet-Proxy/1.0\x0d\x0a\x0d\x0aHTTP/1.1 200 OK\x0d\x0a\x0d\x0aHi there"; - $request->setOutput($output); - - $response = $request->get('answer'); - $this->assertSame('Hi there', $response->getBody()); - } - - /** - * See: https://github.com/codeigniter4/CodeIgniter4/issues/7394 - */ - public function testResponseHeadersWithMultipleRequests(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - ]); - - $output = "HTTP/2.0 200 OK -Server: ddos-guard -Expires: Thu, 19 Nov 1981 08:52:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Pragma: no-cache -Content-Type: application/xml; charset=utf-8 -Transfer-Encoding: chunked\x0d\x0a\x0d\x0aHello1"; - $request->setOutput($output); - - $response = $request->get('answer1'); - - $this->assertSame('Hello1', $response->getBody()); - - $responseHeaderKeys = [ - 'Cache-Control', - 'Server', - 'Expires', - 'Pragma', - 'Content-Type', - 'Transfer-Encoding', - ]; - $this->assertSame($responseHeaderKeys, array_keys($response->headers())); - - $this->assertSame(200, $response->getStatusCode()); - - $output = "HTTP/2.0 200 OK -Expires: Thu, 19 Nov 1982 08:52:00 GMT -Cache-Control: no-store, no-cache, must-revalidate -Content-Type: application/xml; charset=utf-8 -Transfer-Encoding: chunked\x0d\x0a\x0d\x0aHello2"; - $request->setOutput($output); - - $response = $request->get('answer2'); - - $this->assertSame('Hello2', $response->getBody()); - - $responseHeaderKeys = [ - 'Cache-Control', - 'Expires', - 'Content-Type', - 'Transfer-Encoding', - ]; - $this->assertSame($responseHeaderKeys, array_keys($response->headers())); - - $this->assertSame(200, $response->getStatusCode()); - } - - public function testResponseHeadersWithMultipleSetCookies(): void - { - $request = $this->getRequest([ - 'base_uri' => 'https://github.com/', - ]); - - $output = "HTTP/2 200 -server: GitHub.com -date: Sat, 11 Nov 2023 02:26:55 GMT -content-type: text/html; charset=utf-8 -set-cookie: _gh_sess=PlRlha1YumlLhLuo5MuNbIWJRO9RRuR%2FHfYsWRh5B0mkalFIZstlAbTmSstl8q%2FAC57IsWMVuFHWQc6L4qDHQJrwhuYVO5ZaigPCUjAStnhh%2FieZQVqIf92Al7vusuzx2o8XH%2Fv6nd9qzMTAWc2%2FkRsl8jxPQYGNaWeuUBY2w3%2FDORSikN4c0vHOyedhU7Xcv3Ryz5xD3DNxK9R8xKNZ6OSXLJ6bjX8iIT6LxvroVIf2HjvowW9cQsq0kN08mS6KtTnH0mD3ANWqsVVWeMzFNA%3D%3D--Jx830Q9Nmkfz9OGA--kEcPtNphvjNMopYqFDxUbw%3D%3D; Path=/; HttpOnly; Secure; SameSite=Lax -set-cookie: _octo=GH1.1.599292127.1699669625; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; Secure; SameSite=Lax -set-cookie: logged_in=no; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; HttpOnly; Secure; SameSite=Lax -accept-ranges: bytes\x0d\x0a\x0d\x0a"; - $request->setOutput($output); - - $response = $request->get('/'); - - $setCookieHeaders = $response->header('set-cookie'); - - $this->assertCount(3, $setCookieHeaders); - $this->assertSame( - 'logged_in=no; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; HttpOnly; Secure; SameSite=Lax', - $setCookieHeaders[2]->getValue() - ); - - $this->assertSame( - '_octo=GH1.1.599292127.1699669625; Path=/; Domain=github.com; Expires=Mon, 11 Nov 2024 02:27:05 GMT; Secure; SameSite=Lax', - $setCookieHeaders[1]->getValueLine() - ); - } - - public function testSplitResponse(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $request->setOutput("Accept: text/html\x0d\x0a\x0d\x0aHi there"); - $response = $request->get('answer'); - $this->assertSame('Hi there', $response->getBody()); - } - - public function testApplyBody(): void + public function testBodyIsResetOnSecondRequest(): void { $request = $this->getRequest([ 'base_uri' => 'http://www.foo.com/api/v1/', 'delay' => 100, ]); - $request->setBody('name=George'); $request->setOutput('Hi there'); - $response = $request->post('answer'); - - $this->assertSame('Hi there', $response->getBody()); - $this->assertSame('name=George', $request->curl_options[CURLOPT_POSTFIELDS]); - } - - public function testApplyBodyByOptions(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $request->setOutput('Hi there'); - $response = $request->post('answer', [ - 'body' => 'name=George', - ]); - - $this->assertSame('Hi there', $response->getBody()); - $this->assertSame('name=George', $request->curl_options[CURLOPT_POSTFIELDS]); - } - - public function testResponseHeaders(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $request->setOutput("HTTP/2.0 234 Ohoh\x0d\x0aAccept: text/html\x0d\x0a\x0d\x0aHi there"); - $response = $request->get('bogus'); - - $this->assertSame('2.0', $response->getProtocolVersion()); - $this->assertSame(234, $response->getStatusCode()); - } - - public function testResponseHeadersShortProtocol(): void - { - $request = $this->getRequest([ - 'base_uri' => 'http://www.foo.com/api/v1/', - 'delay' => 100, - ]); - - $request->setOutput("HTTP/2 235 Ohoh\x0d\x0aAccept: text/html\x0d\x0a\x0d\x0aHi there shortie"); - $response = $request->get('bogus'); - - $this->assertSame('2.0', $response->getProtocolVersion()); - $this->assertSame(235, $response->getStatusCode()); - } - - public function testPostFormEncoded(): void - { - $params = [ - 'foo' => 'bar', - 'baz' => [ - 'hi', - 'there', - ], - ]; - $this->request->request('POST', '/post', [ - 'form_params' => $params, - ]); - - $this->assertSame('POST', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $expected = http_build_query($params); - $this->assertArrayHasKey(CURLOPT_POSTFIELDS, $options); - $this->assertSame($expected, $options[CURLOPT_POSTFIELDS]); - } - - public function testPostFormMultipart(): void - { - $params = [ - 'foo' => 'bar', - 'baz' => [ - 'hi', - 'there', - ], - 'afile' => new CURLFile(__FILE__), - ]; - $this->request->request('POST', '/post', [ - 'multipart' => $params, - ]); - - $this->assertSame('POST', $this->request->getMethod()); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_POSTFIELDS, $options); - $this->assertSame($params, $options[CURLOPT_POSTFIELDS]); - } - - public function testSetForm(): void - { - $params = [ - 'foo' => 'bar', - 'baz' => [ - 'hi', - 'there', - ], - ]; - - $this->request->setForm($params)->post('/post'); - - $this->assertSame( - http_build_query($params), - $this->request->curl_options[CURLOPT_POSTFIELDS] - ); - - $params['afile'] = new CURLFile(__FILE__); - - $this->request->setForm($params, true)->post('/post'); - - $this->assertSame( - $params, - $this->request->curl_options[CURLOPT_POSTFIELDS] - ); - } - - public function testJSONData(): void - { - $params = [ - 'foo' => 'bar', - 'baz' => [ - 'hi', - 'there', - ], - ]; - $this->request->request('POST', '/post', [ - 'json' => $params, - ]); - - $this->assertSame('POST', $this->request->getMethod()); - - $expected = json_encode($params); - $this->assertSame( - $expected, - $this->request->curl_options[CURLOPT_POSTFIELDS] - ); - $this->assertSame($expected, $this->request->getBody()); - } - - public function testSetJSON(): void - { - $params = [ - 'foo' => 'bar', - 'baz' => [ - 'hi', - 'there', - ], - ]; - $this->request->setJSON($params)->post('/post'); - - $expected = json_encode($params); - $this->assertSame( - $expected, - $this->request->curl_options[CURLOPT_POSTFIELDS] - ); - $this->assertSame($expected, $this->request->getBody()); - - $this->assertSame( - 'Content-Type: application/json', - $this->request->curl_options[CURLOPT_HTTPHEADER][0] - ); - } - - public function testHTTPv1(): void - { - $this->request->request('POST', '/post', [ - 'version' => 1.0, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); - $this->assertSame(CURL_HTTP_VERSION_1_0, $options[CURLOPT_HTTP_VERSION]); - } - - public function testHTTPv11(): void - { - $this->request->request('POST', '/post', [ - 'version' => 1.1, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); - $this->assertSame(CURL_HTTP_VERSION_1_1, $options[CURLOPT_HTTP_VERSION]); - } - - public function testHTTPv2(): void - { - $this->request->request('POST', '/post', [ - 'version' => 2.0, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_HTTP_VERSION, $options); - $this->assertSame(CURL_HTTP_VERSION_2_0, $options[CURLOPT_HTTP_VERSION]); - } - - public function testCookieOption(): void - { - $holder = SUPPORTPATH . 'HTTP/Files/CookiesHolder.txt'; - $this->request->request('POST', '/post', [ - 'cookie' => $holder, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_COOKIEJAR, $options); - $this->assertSame($holder, $options[CURLOPT_COOKIEJAR]); - $this->assertArrayHasKey(CURLOPT_COOKIEFILE, $options); - $this->assertSame($holder, $options[CURLOPT_COOKIEFILE]); - } - - public function testUserAgentOption(): void - { - $agent = 'CodeIgniter Framework'; - - $this->request->request('POST', '/post', [ - 'user_agent' => $agent, - ]); - - $options = $this->request->curl_options; - - $this->assertArrayHasKey(CURLOPT_USERAGENT, $options); - $this->assertSame($agent, $options[CURLOPT_USERAGENT]); - } - - /** - * @see https://github.com/codeigniter4/CodeIgniter4/issues/8347 - */ - public function testMultipleHTTP100(): void - { - $jsonBody = '{"name":"John Doe","age":30}'; - - $output = "HTTP/1.1 100 Continue -Mark bundle as not supporting multiuse -HTTP/1.1 100 Continue -Mark bundle as not supporting multiuse -HTTP/1.1 200 OK -Server: Werkzeug/2.2.2 Python/3.7.17 -Date: Sun, 28 Jan 2024 06:05:36 GMT -Content-Type: application/json -Content-Length: 33\r\n\r\n" . $jsonBody; - - $this->request->setOutput($output); - - $response = $this->request->request('GET', 'http://example.com'); - - $this->assertSame($jsonBody, $response->getBody()); - - $this->assertSame(200, $response->getStatusCode()); - } - - public function testGetHeaderLineContentType(): void - { - $output = 'HTTP/2 200 -date: Thu, 11 Apr 2024 07:26:00 GMT -content-type: text/html; charset=UTF-8 -cache-control: no-store, max-age=0, no-cache -server: cloudflare -content-encoding: br -alt-svc: h3=":443"; ma=86400' . "\x0d\x0a\x0d\x0aResponse Body"; - - $this->request->setOutput($output); - $response = $this->request->request('get', 'http://example.com'); + $request->post('answer'); + $request->post('answer'); - $this->assertSame('text/html; charset=UTF-8', $response->getHeaderLine('Content-Type')); + // The body is not reset! + $this->assertArrayHasKey(CURLOPT_POSTFIELDS, $request->curl_options); } } diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 32d6a4dd919d..722fe1270c02 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -26,10 +26,12 @@ * @internal * * @group Others + * + * @no-final */ -final class CURLRequestTest extends CIUnitTestCase +class CURLRequestTest extends CIUnitTestCase { - private MockCURLRequest $request; + protected MockCURLRequest $request; protected function setUp(): void { From c6c4f812c84afebe8e8dd2344ba2aabfc10130c4 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 18:02:04 +0900 Subject: [PATCH 61/92] docs: add array types --- phpstan-baseline.php | 50 --------------------------- system/HTTP/CURLRequest.php | 2 ++ tests/system/HTTP/CURLRequestTest.php | 3 ++ 3 files changed, 5 insertions(+), 50 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 61841f81795a..3da30e816317 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -5336,11 +5336,6 @@ 'count' => 10, 'path' => __DIR__ . '/system/HTTP/CURLRequest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:__construct\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/HTTP/CURLRequest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:applyBody\\(\\) has parameter \\$curlOptions with no value type specified in iterable type array\\.$#', 'count' => 1, @@ -12901,36 +12896,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/CLIRequestTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'10\' directly on offset \'HTTP_CONTENT_LENGTH\' of \\$_SERVER is discouraged\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'en\\-US\' directly on offset \'HTTP_ACCEPT_LANGUAGE\' of \\$_SERVER is discouraged\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'gzip, deflate, br\' directly on offset \'HTTP_ACCEPT_ENCODING\' of \\$_SERVER is discouraged\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Assigning \'site1\\.com\' directly on offset \'HTTP_HOST\' of \\$_SERVER is discouraged\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestDoNotShareOptionsTest\\:\\:getRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Access to an undefined property CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:\\$curl_options\\.$#', - 'count' => 39, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Assigning \'10\' directly on offset \'HTTP_CONTENT_LENGTH\' of \\$_SERVER is discouraged\\.$#', 'count' => 1, @@ -12951,21 +12916,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Call to an undefined method CodeIgniter\\\\HTTP\\\\CURLRequest\\:\\:setOutput\\(\\)\\.$#', - 'count' => 4, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestTest\\:\\:getRequest\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\CURLRequestTest\\:\\:getRequest\\(\\) has parameter \\$options with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\HTTP\\\\ContentSecurityPolicyTest\\:\\:work\\(\\) has no return type specified\\.$#', 'count' => 1, diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 3040f29b9feb..4b1c9c625399 100644 --- a/system/HTTP/CURLRequest.php +++ b/system/HTTP/CURLRequest.php @@ -107,6 +107,8 @@ class CURLRequest extends OutgoingRequest * - baseURI * - timeout * - any other request options to use as defaults. + * + * @param array $options */ public function __construct(App $config, URI $uri, ?ResponseInterface $response = null, array $options = []) { diff --git a/tests/system/HTTP/CURLRequestTest.php b/tests/system/HTTP/CURLRequestTest.php index 722fe1270c02..1f53a57a8465 100644 --- a/tests/system/HTTP/CURLRequestTest.php +++ b/tests/system/HTTP/CURLRequestTest.php @@ -41,6 +41,9 @@ protected function setUp(): void $this->request = $this->getRequest(); } + /** + * @param array $options + */ protected function getRequest(array $options = []): MockCURLRequest { $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); From 0bb441476b5578722190213beac3056f87e95fe1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 12:00:45 +0900 Subject: [PATCH 62/92] fix: not work for minior update --- admin/create-new-changelog.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/admin/create-new-changelog.php b/admin/create-new-changelog.php index ff371345d166..ff333f42693f 100644 --- a/admin/create-new-changelog.php +++ b/admin/create-new-changelog.php @@ -29,7 +29,9 @@ function replace_file_content(string $path, string $pattern, string $replace): v $isMinorUpdate = ($minorCurrent !== $minor); // Creates a branch for release. -system('git switch develop'); +if (! $isMinorUpdate) { + system('git switch develop'); +} system('git switch -c docs-changelog-' . $version); system('git switch docs-changelog-' . $version); From 349507d8f07aa25cef935dee5e215a520a58c4bc Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 10:31:26 +0900 Subject: [PATCH 63/92] refactor: fix method name (should be lc first) --- system/View/Plugins.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/View/Plugins.php b/system/View/Plugins.php index 19b431a0fab3..7142e44c452e 100644 --- a/system/View/Plugins.php +++ b/system/View/Plugins.php @@ -85,7 +85,7 @@ public static function lang(array $params = []): string * * @param array{field?: string} $params */ - public static function ValidationErrors(array $params = []): string + public static function validationErrors(array $params = []): string { $validator = service('validation'); if ($params === []) { From 7f86e00140b370810f841d2f2513ba74bae4551e Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 10:32:20 +0900 Subject: [PATCH 64/92] test: add test cases --- tests/system/View/ParserPluginTest.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/system/View/ParserPluginTest.php b/tests/system/View/ParserPluginTest.php index d0295ef387b5..9d6b97dec716 100644 --- a/tests/system/View/ParserPluginTest.php +++ b/tests/system/View/ParserPluginTest.php @@ -93,6 +93,10 @@ public function testLang(): void $template = '{+ lang Number.terabyteAbbr +}'; $this->assertSame('TB', $this->parser->renderString($template)); + + $template = '{+ lang Time.years 2024 +}'; + + $this->assertSame('2,024 years', $this->parser->renderString($template)); } public function testValidationErrors(): void @@ -122,6 +126,10 @@ public function testSiteURL(): void $template = '{+ siteURL +}'; $this->assertSame('http://example.com/index.php', $this->parser->renderString($template)); + + $template = '{+ siteURL login +}'; + + $this->assertSame('http://example.com/index.php/login', $this->parser->renderString($template)); } public function testValidationErrorsList(): void From 999f7e42dfc23b5c0b3fc0a009bf890cd82521f8 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 15:29:43 +0900 Subject: [PATCH 65/92] docs: remove unneeded space --- user_guide_src/source/installation/installing_composer.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index 557f81e8d5b8..e4811abd355f 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -89,7 +89,7 @@ the framework version: Then, run the ``composer update`` command. .. note:: If you fix the version number like ``"codeigniter4/framework": "4.4.8"`` - in your **composer.json**, ``composer update`` command will not update the + in your **composer.json**, ``composer update`` command will not update the framework. See `Writing Version Constraints`_ for how to specify the version. .. _Writing Version Constraints: https://getcomposer.org/doc/articles/versions.md#writing-version-constraints @@ -132,7 +132,7 @@ the framework version: Then, run the ``composer update`` command. .. note:: If you fix the version number like ``"codeigniter4/framework": "4.4.8"`` - in your **composer.json**, ``composer update`` command will not update the + in your **composer.json**, ``composer update`` command will not update the framework. See `Writing Version Constraints`_ for how to specify the version. Pros From 9ae7f43a8180457c85c562f913f2e958ed4486fe Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 16:13:13 +0900 Subject: [PATCH 66/92] refactor: update param name --- system/Test/Interfaces/FabricatorModel.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Test/Interfaces/FabricatorModel.php b/system/Test/Interfaces/FabricatorModel.php index d4a4c270919c..186f1d4cc468 100644 --- a/system/Test/Interfaces/FabricatorModel.php +++ b/system/Test/Interfaces/FabricatorModel.php @@ -51,7 +51,7 @@ public function find($id = null); * * @throws ReflectionException */ - public function insert($data = null, bool $returnID = true); + public function insert($row = null, bool $returnID = true); /** * The following properties and methods are optional, but if present should From c02ce684fba57bd17499eea951bcc88853f5e528 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 16:15:15 +0900 Subject: [PATCH 67/92] docs: make array type more precise --- system/Test/Interfaces/FabricatorModel.php | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/system/Test/Interfaces/FabricatorModel.php b/system/Test/Interfaces/FabricatorModel.php index 186f1d4cc468..a5860e22fb83 100644 --- a/system/Test/Interfaces/FabricatorModel.php +++ b/system/Test/Interfaces/FabricatorModel.php @@ -13,6 +13,7 @@ namespace CodeIgniter\Test\Interfaces; +use CodeIgniter\BaseModel; use Faker\Generator; use ReflectionException; @@ -27,6 +28,8 @@ * @property string $returnType * @property string $primaryKey * @property string $dateFormat + * + * @phpstan-import-type row_array from BaseModel */ interface FabricatorModel { @@ -34,9 +37,9 @@ interface FabricatorModel * Fetches the row of database from $this->table with a primary key * matching $id. * - * @param array|mixed|null $id One primary key or an array of primary keys + * @param int|list|string|null $id One primary key or an array of primary keys * - * @return array|object|null The resulting row of data, or null. + * @phpstan-return ($id is int|string ? row_array|object|null : list) */ public function find($id = null); @@ -44,8 +47,9 @@ public function find($id = null); * Inserts data into the current table. If an object is provided, * it will attempt to convert it to an array. * - * @param array|object $data - * @param bool $returnID Whether insert ID should be returned or not. + * @param array|object|null $row + * @phpstan-param row_array|object|null $row + * @param bool $returnID Whether insert ID should be returned or not. * * @return bool|int|string * From 3cd7572f0dbcd5397f2ef7d9c6b9fdb52e7d0f79 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 16:15:57 +0900 Subject: [PATCH 68/92] refactor: add return type --- tests/_support/Models/FabricatorModel.php | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/_support/Models/FabricatorModel.php b/tests/_support/Models/FabricatorModel.php index 2903b5036402..1cae9394b9a3 100644 --- a/tests/_support/Models/FabricatorModel.php +++ b/tests/_support/Models/FabricatorModel.php @@ -28,8 +28,10 @@ class FabricatorModel extends Model 'description', ]; - // Return a faked entity - public function fake(Generator &$faker) + /** + * Return a faked entity + */ + public function fake(Generator &$faker): object { return (object) [ 'name' => $faker->ipv4(), From b7443388303801737cbbafb157f2bb5415821eaf Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 16:16:18 +0900 Subject: [PATCH 69/92] chore: update phpstan-baseline --- phpstan-baseline.php | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index dd91befad54a..5734ae93e1ef 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -8616,16 +8616,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Test/Fabricator.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Test\\\\Interfaces\\\\FabricatorModel\\:\\:find\\(\\) return type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Test/Interfaces/FabricatorModel.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Test\\\\Interfaces\\\\FabricatorModel\\:\\:insert\\(\\) has parameter \\$data with no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Test/Interfaces/FabricatorModel.php', -]; $ignoreErrors[] = [ 'message' => '#^Property CodeIgniter\\\\Test\\\\Mock\\\\MockBuilder\\:\\:\\$supportedIgnoreStatements type has no value type specified in iterable type array\\.$#', 'count' => 1, @@ -10401,11 +10391,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/_support/Models/EventModel.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method Tests\\\\Support\\\\Models\\\\FabricatorModel\\:\\:fake\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/_support/Models/FabricatorModel.php', -]; $ignoreErrors[] = [ 'message' => '#^Property Tests\\\\Support\\\\Models\\\\JobModel\\:\\:\\$description has no type specified\\.$#', 'count' => 1, From ba4d372b52c3f8d9bebae84a8d6dad2616b21f17 Mon Sep 17 00:00:00 2001 From: kenjis Date: Fri, 12 Apr 2024 16:26:48 +0900 Subject: [PATCH 70/92] docs: add method stubs to sample Model code --- user_guide_src/source/testing/fabricator/001.php | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/user_guide_src/source/testing/fabricator/001.php b/user_guide_src/source/testing/fabricator/001.php index 8fbf136032ca..f237d56b1324 100644 --- a/user_guide_src/source/testing/fabricator/001.php +++ b/user_guide_src/source/testing/fabricator/001.php @@ -6,5 +6,15 @@ class MyModel implements FabricatorModel { + public function find($id = null) + { + // TODO: Implement find() method. + } + + public function insert($row = null, bool $returnID = true) + { + // TODO: Implement insert() method. + } + // ... } From fd782e70b03f0d2cf73036d0ed45adf958def20a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Wed, 10 Apr 2024 16:08:51 +0300 Subject: [PATCH 71/92] refactor: system/Debug/Toolbar/Collectors/Routes.php --- phpstan-baseline.php | 5 ----- system/Debug/Toolbar/Collectors/Routes.php | 19 +++++++++++++++++++ 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index dd91befad54a..0d6049d02bac 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -4446,11 +4446,6 @@ 'count' => 1, 'path' => __DIR__ . '/system/Debug/Toolbar/Collectors/Logs.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Debug\\\\Toolbar\\\\Collectors\\\\Routes\\:\\:display\\(\\) return type has no value type specified in iterable type array\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/system/Debug/Toolbar/Collectors/Routes.php', -]; $ignoreErrors[] = [ 'message' => '#^Method CodeIgniter\\\\Debug\\\\Toolbar\\\\Collectors\\\\Timers\\:\\:formatTimelineData\\(\\) return type has no value type specified in iterable type array\\.$#', 'count' => 1, diff --git a/system/Debug/Toolbar/Collectors/Routes.php b/system/Debug/Toolbar/Collectors/Routes.php index 737c86bff692..2dc03dce9651 100644 --- a/system/Debug/Toolbar/Collectors/Routes.php +++ b/system/Debug/Toolbar/Collectors/Routes.php @@ -51,6 +51,25 @@ class Routes extends BaseCollector /** * Returns the data of this collector to be formatted in the toolbar * + * @return array{ + * matchedRoute: array + * }>, + * routes: array + * } + * * @throws ReflectionException */ public function display(): array From 528e51386ccd758b035cdee42e01a7b19077b406 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mehmet=20=C3=87a=C4=9Fda=C5=9F=20SAYGILI?= Date: Fri, 12 Apr 2024 17:55:16 +0300 Subject: [PATCH 72/92] apply suggestions. --- system/Debug/Toolbar/Collectors/Routes.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Debug/Toolbar/Collectors/Routes.php b/system/Debug/Toolbar/Collectors/Routes.php index 2dc03dce9651..b6862dcee73c 100644 --- a/system/Debug/Toolbar/Collectors/Routes.php +++ b/system/Debug/Toolbar/Collectors/Routes.php @@ -58,12 +58,12 @@ class Routes extends BaseCollector * method: string, * paramCount: int, * truePCount: int, - * params: array * }>, - * routes: array Date: Sat, 13 Apr 2024 06:48:37 +0900 Subject: [PATCH 73/92] docs: fix by proofreading Co-authored-by: Michal Sniatala --- .../source/installation/installing_composer.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index e4811abd355f..3dd4c2a6a1b7 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -88,9 +88,9 @@ the framework version: Then, run the ``composer update`` command. -.. note:: If you fix the version number like ``"codeigniter4/framework": "4.4.8"`` +.. note:: When you use a fixed version number like ``"codeigniter4/framework": "4.4.8"`` in your **composer.json**, ``composer update`` command will not update the - framework. See `Writing Version Constraints`_ for how to specify the version. + framework to the latest version. See `Writing Version Constraints`_ for how to specify the version. .. _Writing Version Constraints: https://getcomposer.org/doc/articles/versions.md#writing-version-constraints @@ -131,9 +131,9 @@ the framework version: Then, run the ``composer update`` command. -.. note:: If you fix the version number like ``"codeigniter4/framework": "4.4.8"`` +.. note:: When you use a fixed version number like ``"codeigniter4/framework": "4.4.8"`` in your **composer.json**, ``composer update`` command will not update the - framework. See `Writing Version Constraints`_ for how to specify the version. + framework to the latest version. See `Writing Version Constraints`_ for how to specify the version. Pros ---- @@ -272,7 +272,7 @@ and check Breaking Changes and Enhancements. Upgrading to a Specified Version ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -For example, you may want to upgrade to v4.4.8 after v4.5.0 has been released. +For example, you may want to upgrade from v4.4.7 to v4.4.8 after v4.5.0 has been released. In that case, open **composer.json** in your project root folder, and specify the framework version: From bdf9cea8eeca2a605d284af430502261a9d1ad6e Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 09:07:43 +0900 Subject: [PATCH 74/92] docs: add README.md --- admin/css/debug-toolbar/README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 admin/css/debug-toolbar/README.md diff --git a/admin/css/debug-toolbar/README.md b/admin/css/debug-toolbar/README.md new file mode 100644 index 000000000000..2c70e8147eae --- /dev/null +++ b/admin/css/debug-toolbar/README.md @@ -0,0 +1 @@ +See [contributing/css.md](../../../contributing/css.md). From 60f54c02be6e025d1606d070c1beaf792cd4b806 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 09:07:57 +0900 Subject: [PATCH 75/92] docs: remove unneeded "`" --- contributing/css.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contributing/css.md b/contributing/css.md index 267d4f7a5609..4de86e069973 100644 --- a/contributing/css.md +++ b/contributing/css.md @@ -10,7 +10,7 @@ Open your terminal, and navigate to CodeIgniter's root folder. To generate the CSS file, use the following command: ```console -sass --no-source-map admin/css/debug-toolbar/toolbar.scss system/Debug/Toolbar/Views/toolbar.css` +sass --no-source-map admin/css/debug-toolbar/toolbar.scss system/Debug/Toolbar/Views/toolbar.css ``` Details: From b32370249e26d80d12fb789043a909453264e45c Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 09:09:03 +0900 Subject: [PATCH 76/92] refactory: remove unneeded `px` --- admin/css/debug-toolbar/toolbar.scss | 4 ++-- system/Debug/Toolbar/Views/toolbar.css | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/admin/css/debug-toolbar/toolbar.scss b/admin/css/debug-toolbar/toolbar.scss index e129a4b1c5b6..f7d3c0d08d77 100644 --- a/admin/css/debug-toolbar/toolbar.scss +++ b/admin/css/debug-toolbar/toolbar.scss @@ -28,8 +28,8 @@ width: 36px; // Spacing - margin: 0px; - padding: 0px; + margin: 0; + padding: 0; // Content clear: both; diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index 4154f4c5c4ca..82d40fe8c4e7 100644 --- a/system/Debug/Toolbar/Views/toolbar.css +++ b/system/Debug/Toolbar/Views/toolbar.css @@ -13,8 +13,8 @@ z-index: 10000; height: 36px; width: 36px; - margin: 0px; - padding: 0px; + margin: 0; + padding: 0; clear: both; text-align: center; cursor: pointer; From cd6ba4822607f94bf6836e05720e54d0d7134598 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 09:09:31 +0900 Subject: [PATCH 77/92] fix: add padding and font-family If a dev changes CSS for h1, the toolbar dislpay will be broken. --- admin/css/debug-toolbar/toolbar.scss | 2 ++ system/Debug/Toolbar/Views/toolbar.css | 2 ++ 2 files changed, 4 insertions(+) diff --git a/admin/css/debug-toolbar/toolbar.scss b/admin/css/debug-toolbar/toolbar.scss index f7d3c0d08d77..97a92690b937 100644 --- a/admin/css/debug-toolbar/toolbar.scss +++ b/admin/css/debug-toolbar/toolbar.scss @@ -85,6 +85,8 @@ display: flex; font-weight: normal; margin: 0 0 0 auto; + padding: 0; + font-family: $base-font; svg { width: 16px; diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index 82d40fe8c4e7..2e165b825e99 100644 --- a/system/Debug/Toolbar/Views/toolbar.css +++ b/system/Debug/Toolbar/Views/toolbar.css @@ -52,6 +52,8 @@ display: flex; font-weight: normal; margin: 0 0 0 auto; + padding: 0; + font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; } #debug-bar h1 svg { width: 16px; From 8a76cb67719f2e45aa4f026b7cf3a7b28ca6fcfb Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 11:55:48 +0900 Subject: [PATCH 78/92] chore: move PHPUnit cache to build/ --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 45b6b07231c4..d97e10c0244f 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -4,7 +4,7 @@ bootstrap="system/Test/bootstrap.php" backupGlobals="false" beStrictAboutOutputDuringTests="true" colors="true" columns="max" failOnRisky="true" failOnWarning="true" - cacheDirectory=".phpunit.cache"> + cacheDirectory="build/.phpunit.cache"> From b8655869c72f85eecbf26660d6c03f67c5e6fbc9 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 13:41:50 +0900 Subject: [PATCH 79/92] docs: fix Postgre DSN sample See "Table 33.1. SSL Mode Descriptions" in https://www.postgresql.org/docs/12/libpq-ssl.html#LIBPQ-SSL-PROTECTION --- user_guide_src/source/database/configuration/010.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/user_guide_src/source/database/configuration/010.php b/user_guide_src/source/database/configuration/010.php index de06d231b015..d1f89b31fa64 100644 --- a/user_guide_src/source/database/configuration/010.php +++ b/user_guide_src/source/database/configuration/010.php @@ -10,7 +10,7 @@ class Database extends Config // Postgre public array $default = [ - 'DSN' => 'Postgre://username:password@hostname:5432/database?charset=utf8&connect_timeout=5&sslmode=1', + 'DSN' => 'Postgre://username:password@hostname:5432/database?charset=utf8&connect_timeout=5&sslmode=require', // ... ]; From 7b3a01a297ed0e03f4b93f9fe9df0f40157181ef Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:20:51 +0900 Subject: [PATCH 80/92] chore: change coding style --- phpunit.xml.dist | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index d97e10c0244f..6d2cf4c07478 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,10 +1,15 @@ - + From 930a44ff66252a8c8d00cff21f85d3bf31a836f7 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:24:05 +0900 Subject: [PATCH 81/92] chore: change coding style --- admin/framework/phpunit.xml.dist | 102 +++++++++++++++++-------------- admin/starter/phpunit.xml.dist | 102 +++++++++++++++++-------------- 2 files changed, 112 insertions(+), 92 deletions(-) diff --git a/admin/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index 0235b8a739c1..f159284ba4ba 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -1,48 +1,58 @@ - - - - - - - - - - - - ./tests - - - - - - - - - - - - - - - - - - - - - ./app - - - ./app/Views - ./app/Config/Routes.php - - + + + + + + + + + + + + ./tests + + + + + + + + + + + + + + + + + + + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index 7cd6d3af600a..6727513624a9 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -1,48 +1,58 @@ - - - - - - - - - - - - ./tests - - - - - - - - - - - - - - - - - - - - - ./app - - - ./app/Views - ./app/Config/Routes.php - - + + + + + + + + + + + + ./tests + + + + + + + + + + + + + + + + + + + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + From fc303daf755b72ba5507c0eacee10dafc464b759 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:29:09 +0900 Subject: [PATCH 82/92] chore: update PHPUnit schema version --- phpunit.xml.dist | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 6d2cf4c07478..ea45832f9566 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,7 +1,7 @@ Date: Sat, 13 Apr 2024 18:30:48 +0900 Subject: [PATCH 83/92] chore: move PHPUnit cache to build/ --- admin/framework/phpunit.xml.dist | 2 +- admin/starter/phpunit.xml.dist | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/admin/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index f159284ba4ba..dba006b5a13d 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -9,7 +9,7 @@ stopOnIncomplete="false" stopOnSkipped="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" - cacheDirectory=".phpunit.cache"> + cacheDirectory="build/.phpunit.cache"> diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index 6727513624a9..a3f4c958a7b5 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -9,7 +9,7 @@ stopOnIncomplete="false" stopOnSkipped="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" - cacheDirectory=".phpunit.cache"> + cacheDirectory="build/.phpunit.cache"> From 601593679c06e46f01b5d4a081b502de8152794c Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:30:59 +0900 Subject: [PATCH 84/92] chore: change attribute order Make the same as the main repositoy's phpunit.xml.dist. --- admin/framework/phpunit.xml.dist | 10 +++++----- admin/starter/phpunit.xml.dist | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/admin/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index dba006b5a13d..5f51d97f922c 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -1,14 +1,14 @@ diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index a3f4c958a7b5..5f51d97f922c 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -1,14 +1,14 @@ From 43889b151b21564787778af0db0847ccd97a86d3 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:38:26 +0900 Subject: [PATCH 85/92] chore: add default attributes to coverage No change will be made. --- admin/framework/phpunit.xml.dist | 6 +++++- admin/starter/phpunit.xml.dist | 6 +++++- phpunit.xml.dist | 6 +++++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/admin/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index 5f51d97f922c..1dc6c6fbbe98 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -10,7 +10,11 @@ failOnRisky="true" failOnWarning="true" cacheDirectory="build/.phpunit.cache"> - + diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index 5f51d97f922c..1dc6c6fbbe98 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -10,7 +10,11 @@ failOnRisky="true" failOnWarning="true" cacheDirectory="build/.phpunit.cache"> - + diff --git a/phpunit.xml.dist b/phpunit.xml.dist index ea45832f9566..7464323e4078 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -10,7 +10,11 @@ failOnRisky="true" failOnWarning="true" cacheDirectory="build/.phpunit.cache"> - + From e7fca57c38cec44e8c6dad99c758e96b892a053f Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:44:08 +0900 Subject: [PATCH 86/92] chore: move up --- admin/framework/phpunit.xml.dist | 18 +++++++++--------- admin/starter/phpunit.xml.dist | 18 +++++++++--------- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/admin/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index 1dc6c6fbbe98..5f0c2e9a2f76 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -32,6 +32,15 @@ + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + @@ -50,13 +59,4 @@ --> - - - ./app - - - ./app/Views - ./app/Config/Routes.php - - diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index 1dc6c6fbbe98..5f0c2e9a2f76 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -32,6 +32,15 @@ + + + ./app + + + ./app/Views + ./app/Config/Routes.php + + @@ -50,13 +59,4 @@ --> - - - ./app - - - ./app/Views - ./app/Config/Routes.php - - From 2c112a6ebe264fbc55c2d34acc8708c19520ced5 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:53:40 +0900 Subject: [PATCH 87/92] chore: add CODEIGNITER_SCREAM_DEPRECATIONS but disabled --- admin/framework/phpunit.xml.dist | 1 + admin/starter/phpunit.xml.dist | 1 + 2 files changed, 2 insertions(+) diff --git a/admin/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index 5f0c2e9a2f76..dea940878617 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -43,6 +43,7 @@ + diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index 5f0c2e9a2f76..dea940878617 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -43,6 +43,7 @@ + From 754309e78217feba2b1e3fc73de42b80a22564ac Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 18:57:04 +0900 Subject: [PATCH 88/92] chore: update .gitignore --- .gitignore | 2 -- admin/framework/.gitignore | 2 -- admin/starter/.gitignore | 2 -- 3 files changed, 6 deletions(-) diff --git a/.gitignore b/.gitignore index 0334b660bb60..988be09b1948 100644 --- a/.gitignore +++ b/.gitignore @@ -125,7 +125,5 @@ nb-configuration.xml /results/ /phpunit*.xml -/.phpunit.*.cache -/.phpunit.cache /.php-cs-fixer.php diff --git a/admin/framework/.gitignore b/admin/framework/.gitignore index 696da9cb0a91..8071bd3d07f8 100644 --- a/admin/framework/.gitignore +++ b/admin/framework/.gitignore @@ -124,5 +124,3 @@ nb-configuration.xml /results/ /phpunit*.xml -/.phpunit.*.cache - diff --git a/admin/starter/.gitignore b/admin/starter/.gitignore index 696da9cb0a91..8071bd3d07f8 100644 --- a/admin/starter/.gitignore +++ b/admin/starter/.gitignore @@ -124,5 +124,3 @@ nb-configuration.xml /results/ /phpunit*.xml -/.phpunit.*.cache - From 9f850f79d9e5cd81a59ff04131133741f84f9fa1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sat, 13 Apr 2024 21:53:03 +0900 Subject: [PATCH 89/92] fix: Cannot declare class CodeIgniter\Config\Services, because the name is already in use See https://github.com/codeigniter4/CodeIgniter4/pull/8745#issuecomment-2052569997 --- system/Config/BaseService.php | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/system/Config/BaseService.php b/system/Config/BaseService.php index 2f8df2a35420..cd770dc667ed 100644 --- a/system/Config/BaseService.php +++ b/system/Config/BaseService.php @@ -389,8 +389,15 @@ protected static function buildServicesCache(): void $locator = static::locator(); $files = $locator->search('Config/Services'); + $systemPath = static::autoloader()->getNamespace('CodeIgniter')[0]; + // Get instances of all service classes and cache them locally. foreach ($files as $file) { + // Does not search `CodeIgniter` namespace to prevent from loading twice. + if (str_starts_with($file, $systemPath)) { + continue; + } + $classname = $locator->findQualifiedNameFromPath($file); if ($classname === false) { From d4f15146a0c02fcdca4f6fb60a6d237541c33218 Mon Sep 17 00:00:00 2001 From: obozdag Date: Sat, 13 Apr 2024 19:17:17 +0200 Subject: [PATCH 90/92] docs: Small typo in routing.rst Fix "a HTTP" to "an HTTP" --- user_guide_src/source/incoming/routing.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 134b0e248134..2515d1a888b9 100644 --- a/user_guide_src/source/incoming/routing.rst +++ b/user_guide_src/source/incoming/routing.rst @@ -814,7 +814,7 @@ Consider this URI:: example.com/index.php/helloworld/hello/1 -In the above example, when you send a HTTP request with **GET** method, +In the above example, when you send an HTTP request with **GET** method, Auto Routing would attempt to find a controller named ``App\Controllers\Helloworld`` and executes ``getHello()`` method with passing ``'1'`` as the first argument. @@ -918,7 +918,7 @@ or to use :ref:`auto-routing-improved`, Auto Routing (Legacy) feature. It is easy to create vulnerable apps where controller filters or CSRF protection are bypassed. -.. important:: Auto Routing (Legacy) routes a HTTP request with **any** HTTP method to a controller method. +.. important:: Auto Routing (Legacy) routes an HTTP request with **any** HTTP method to a controller method. Enable Auto Routing (Legacy) ============================ From c6de161db89a9fd1bad8fa819e02320d91dc2402 Mon Sep 17 00:00:00 2001 From: obozdag Date: Sat, 13 Apr 2024 19:20:02 +0200 Subject: [PATCH 91/92] docs: Small typo in controllers.rst Fix "a HTTP" to "an HTTP". --- user_guide_src/source/incoming/controllers.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/user_guide_src/source/incoming/controllers.rst b/user_guide_src/source/incoming/controllers.rst index dcbe950b2e36..bd1f011df78b 100644 --- a/user_guide_src/source/incoming/controllers.rst +++ b/user_guide_src/source/incoming/controllers.rst @@ -11,7 +11,7 @@ Controllers are the heart of your application, as they determine how HTTP reques What is a Controller? ********************* -A Controller is simply a class file that handles a HTTP request. +A Controller is simply a class file that handles an HTTP request. :doc:`URI Routing ` associates a URI with a controller. It returns a view string or ``Response`` object. @@ -477,7 +477,7 @@ without route definitions. The auto-routing is disabled by default. Auto Routing (Legacy). It is easy to create vulnerable apps where controller filters or CSRF protection are bypassed. -.. important:: Auto Routing (Legacy) routes a HTTP request with **any** HTTP method to a controller method. +.. important:: Auto Routing (Legacy) routes an HTTP request with **any** HTTP method to a controller method. .. important:: Since v4.5.0, if Auto Routing (Legacy) doesn't find the controller, it will throw ``PageNotFoundException`` exception before the Controller Filters From 092231850b70a7c3017a0beb7198388735fb0211 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 14 Apr 2024 12:05:41 +0900 Subject: [PATCH 92/92] Prep for 4.5.1 release --- CHANGELOG.md | 29 +++++++++++++++++ phpdoc.dist.xml | 2 +- system/CodeIgniter.php | 2 +- user_guide_src/source/changelogs/v4.5.1.rst | 18 +---------- user_guide_src/source/conf.py | 2 +- .../source/installation/upgrade_451.rst | 32 +++++-------------- 6 files changed, 41 insertions(+), 44 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 60950f4cf0f0..5148b0faad05 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,34 @@ # Changelog +## [v4.5.1](https://github.com/codeigniter4/CodeIgniter4/tree/v4.5.1) (2024-04-14) +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.5.0...v4.5.1) + +### Fixed Bugs + +* fix: TypeError in form() by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8736 +* fix: [DebugBar] TypeError in Toolbar by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8727 +* fix: TypeError when Time is passed to Model by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8738 +* docs: added Config\Feature::$oldFilterOrder to app/Config/Feature.php… by @mullernato in https://github.com/codeigniter4/CodeIgniter4/pull/8749 +* fix: Factories::get() cannot get defined classes by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8744 +* fix: `BaseConnection::escape()` does not accept Stringable by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8756 +* fix: [CURLRequest] `getHeaderLine('Content-Type')` causes InvalidArgumentException by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8760 +* fix: [CURLRequest] construct param $config is not used by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8761 +* fix: [FileLocator] Cannot declare class XXX, because the name is already in use by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8745 +* fix: [DebugBar] Toolbar display may be broken by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8772 +* fix: Cannot declare class CodeIgniter\Config\Services, because the name is already in use by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8776 +* docs: fix Postgre DSN sample by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8774 + +### Refactoring + +* test: refactor Config/Registrar.php by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8731 +* test: add return void by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8746 +* refactor: system/CLI/BaseCommand.php by @mcsaygili in https://github.com/codeigniter4/CodeIgniter4/pull/8741 +* refactor: system/View/Plugins.php by @mcsaygili in https://github.com/codeigniter4/CodeIgniter4/pull/8742 +* refactor: fix method name `ValidationErrors` in View\Plugins by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8758 +* refactor: system/Debug/Toolbar/Collectors/Routes.php by @mcsaygili in https://github.com/codeigniter4/CodeIgniter4/pull/8751 +* refactor: improve error message in BaseExceptionHandler by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8766 +* refactor: FabricatorModel by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/8770 + ## [v4.5.0](https://github.com/codeigniter4/CodeIgniter4/tree/v4.5.0) (2024-04-07) [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.4.8...v4.5.0) diff --git a/phpdoc.dist.xml b/phpdoc.dist.xml index b93122ac193f..546630d3f446 100644 --- a/phpdoc.dist.xml +++ b/phpdoc.dist.xml @@ -10,7 +10,7 @@ api/build/ api/cache/ - + system diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 7fdade26fb99..1758228076ab 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -56,7 +56,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.5.0'; + public const CI_VERSION = '4.5.1'; /** * App startup time. diff --git a/user_guide_src/source/changelogs/v4.5.1.rst b/user_guide_src/source/changelogs/v4.5.1.rst index 9f00193bcf6c..c2407f651ae1 100644 --- a/user_guide_src/source/changelogs/v4.5.1.rst +++ b/user_guide_src/source/changelogs/v4.5.1.rst @@ -2,7 +2,7 @@ Version 4.5.1 ############# -Release Date: Unreleased +Release Date: April 14, 2024 **4.5.1 release of CodeIgniter4** @@ -10,22 +10,6 @@ Release Date: Unreleased :local: :depth: 3 -******** -BREAKING -******** - -*************** -Message Changes -*************** - -******* -Changes -******* - -************ -Deprecations -************ - ********** Bugs Fixed ********** diff --git a/user_guide_src/source/conf.py b/user_guide_src/source/conf.py index 100b9cb012cb..1bc7efd9d0ab 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -26,7 +26,7 @@ version = '4.5' # The full version, including alpha/beta/rc tags. -release = '4.5.0' +release = '4.5.1' # -- General configuration --------------------------------------------------- diff --git a/user_guide_src/source/installation/upgrade_451.rst b/user_guide_src/source/installation/upgrade_451.rst index 3fc97dc3cffe..2900209474f0 100644 --- a/user_guide_src/source/installation/upgrade_451.rst +++ b/user_guide_src/source/installation/upgrade_451.rst @@ -12,18 +12,6 @@ Please refer to the upgrade instructions corresponding to your installation meth :local: :depth: 2 -********************** -Mandatory File Changes -********************** - -**************** -Breaking Changes -**************** - -********************* -Breaking Enhancements -********************* - ************* Project Files ************* @@ -34,21 +22,17 @@ these files being outside of the **system** scope they will not be changed witho There are some third-party CodeIgniter modules available to assist with merging changes to the project space: `Explore on Packagist `_. -Content Changes -=============== - -The following files received significant changes (including deprecations or visual adjustments) -and it is recommended that you merge the updated versions with your application: - -Config ------- - -- @TODO - All Changes =========== This is a list of all files in the **project space** that received changes; many will be simple comments or formatting that have no effect on the runtime: -- @TODO +- .gitignore +- composer.json +- phpunit.xml.dist +- tests/.htaccess +- tests/index.html +- writable/debugbar/.gitkeep (Removed) +- writable/debugbar/index.html +- writable/index.html