diff --git a/.gitignore b/.gitignore index 71cf213fbfaf..988be09b1948 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 @@ -125,7 +125,5 @@ nb-configuration.xml /results/ /phpunit*.xml -/.phpunit.*.cache -/.phpunit.cache /.php-cs-fixer.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 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of CodeIgniter 4 framework. + * + * (c) CodeIgniter Foundation <admin@codeigniter.com> + * + * 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/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/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` 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); 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). diff --git a/admin/css/debug-toolbar/toolbar.scss b/admin/css/debug-toolbar/toolbar.scss index e129a4b1c5b6..97a92690b937 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; @@ -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/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/framework/phpunit.xml.dist b/admin/framework/phpunit.xml.dist index 0235b8a739c1..dea940878617 100644 --- a/admin/framework/phpunit.xml.dist +++ b/admin/framework/phpunit.xml.dist @@ -1,48 +1,63 @@ <?xml version="1.0" encoding="UTF-8"?> -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="system/Test/bootstrap.php" backupGlobals="false" colors="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache"> - <coverage includeUncoveredFiles="true"> - <report> - <clover outputFile="build/logs/clover.xml"/> - <html outputDirectory="build/logs/html"/> - <php outputFile="build/logs/coverage.serialized"/> - <text outputFile="php://stdout" showUncoveredFiles="false"/> - </report> - </coverage> - <testsuites> - <testsuite name="App"> - <directory>./tests</directory> - </testsuite> - </testsuites> - <logging> - <testdoxHtml outputFile="build/logs/testdox.html"/> - <testdoxText outputFile="build/logs/testdox.txt"/> - <junit outputFile="build/logs/logfile.xml"/> - </logging> - <php> - <server name="app.baseURL" value="http://example.com/"/> - <!-- Directory containing phpunit.xml --> - <const name="HOMEPATH" value="./"/> - <!-- Directory containing the Paths config file --> - <const name="CONFIGPATH" value="./app/Config/"/> - <!-- Directory containing the front controller (index.php) --> - <const name="PUBLICPATH" value="./public/"/> - <!-- Database configuration --> - <!-- Uncomment to provide your own database for testing - <env name="database.tests.hostname" value="localhost"/> - <env name="database.tests.database" value="tests"/> - <env name="database.tests.username" value="tests_user"/> - <env name="database.tests.password" value=""/> - <env name="database.tests.DBDriver" value="MySQLi"/> - <env name="database.tests.DBPrefix" value="tests_"/> - --> - </php> - <source> - <include> - <directory suffix=".php">./app</directory> - </include> - <exclude> - <directory suffix=".php">./app/Views</directory> - <file>./app/Config/Routes.php</file> - </exclude> - </source> +<phpunit + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" + bootstrap="system/Test/bootstrap.php" + backupGlobals="false" + beStrictAboutOutputDuringTests="true" + colors="true" + columns="max" + failOnRisky="true" + failOnWarning="true" + cacheDirectory="build/.phpunit.cache"> + <coverage + includeUncoveredFiles="true" + pathCoverage="false" + ignoreDeprecatedCodeUnits="true" + disableCodeCoverageIgnore="true"> + <report> + <clover outputFile="build/logs/clover.xml"/> + <html outputDirectory="build/logs/html"/> + <php outputFile="build/logs/coverage.serialized"/> + <text outputFile="php://stdout" showUncoveredFiles="false"/> + </report> + </coverage> + <testsuites> + <testsuite name="App"> + <directory>./tests</directory> + </testsuite> + </testsuites> + <logging> + <testdoxHtml outputFile="build/logs/testdox.html"/> + <testdoxText outputFile="build/logs/testdox.txt"/> + <junit outputFile="build/logs/logfile.xml"/> + </logging> + <source> + <include> + <directory suffix=".php">./app</directory> + </include> + <exclude> + <directory suffix=".php">./app/Views</directory> + <file>./app/Config/Routes.php</file> + </exclude> + </source> + <php> + <server name="app.baseURL" value="http://example.com/"/> + <server name="CODEIGNITER_SCREAM_DEPRECATIONS" value="0"/> + <!-- Directory containing phpunit.xml --> + <const name="HOMEPATH" value="./"/> + <!-- Directory containing the Paths config file --> + <const name="CONFIGPATH" value="./app/Config/"/> + <!-- Directory containing the front controller (index.php) --> + <const name="PUBLICPATH" value="./public/"/> + <!-- Database configuration --> + <!-- Uncomment to provide your own database for testing + <env name="database.tests.hostname" value="localhost"/> + <env name="database.tests.database" value="tests"/> + <env name="database.tests.username" value="tests_user"/> + <env name="database.tests.password" value=""/> + <env name="database.tests.DBDriver" value="MySQLi"/> + <env name="database.tests.DBPrefix" value="tests_"/> + --> + </php> </phpunit> 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 - diff --git a/admin/starter/phpunit.xml.dist b/admin/starter/phpunit.xml.dist index 7cd6d3af600a..dea940878617 100644 --- a/admin/starter/phpunit.xml.dist +++ b/admin/starter/phpunit.xml.dist @@ -1,48 +1,63 @@ <?xml version="1.0" encoding="UTF-8"?> -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" bootstrap="vendor/codeigniter4/framework/system/Test/bootstrap.php" backupGlobals="false" colors="true" stopOnError="false" stopOnFailure="false" stopOnIncomplete="false" stopOnSkipped="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" cacheDirectory=".phpunit.cache"> - <coverage includeUncoveredFiles="true"> - <report> - <clover outputFile="build/logs/clover.xml"/> - <html outputDirectory="build/logs/html"/> - <php outputFile="build/logs/coverage.serialized"/> - <text outputFile="php://stdout" showUncoveredFiles="false"/> - </report> - </coverage> - <testsuites> - <testsuite name="App"> - <directory>./tests</directory> - </testsuite> - </testsuites> - <logging> - <testdoxHtml outputFile="build/logs/testdox.html"/> - <testdoxText outputFile="build/logs/testdox.txt"/> - <junit outputFile="build/logs/logfile.xml"/> - </logging> - <php> - <server name="app.baseURL" value="http://example.com/"/> - <!-- Directory containing phpunit.xml --> - <const name="HOMEPATH" value="./"/> - <!-- Directory containing the Paths config file --> - <const name="CONFIGPATH" value="./app/Config/"/> - <!-- Directory containing the front controller (index.php) --> - <const name="PUBLICPATH" value="./public/"/> - <!-- Database configuration --> - <!-- Uncomment to provide your own database for testing - <env name="database.tests.hostname" value="localhost"/> - <env name="database.tests.database" value="tests"/> - <env name="database.tests.username" value="tests_user"/> - <env name="database.tests.password" value=""/> - <env name="database.tests.DBDriver" value="MySQLi"/> - <env name="database.tests.DBPrefix" value="tests_"/> - --> - </php> - <source> - <include> - <directory suffix=".php">./app</directory> - </include> - <exclude> - <directory suffix=".php">./app/Views</directory> - <file>./app/Config/Routes.php</file> - </exclude> - </source> +<phpunit + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" + bootstrap="system/Test/bootstrap.php" + backupGlobals="false" + beStrictAboutOutputDuringTests="true" + colors="true" + columns="max" + failOnRisky="true" + failOnWarning="true" + cacheDirectory="build/.phpunit.cache"> + <coverage + includeUncoveredFiles="true" + pathCoverage="false" + ignoreDeprecatedCodeUnits="true" + disableCodeCoverageIgnore="true"> + <report> + <clover outputFile="build/logs/clover.xml"/> + <html outputDirectory="build/logs/html"/> + <php outputFile="build/logs/coverage.serialized"/> + <text outputFile="php://stdout" showUncoveredFiles="false"/> + </report> + </coverage> + <testsuites> + <testsuite name="App"> + <directory>./tests</directory> + </testsuite> + </testsuites> + <logging> + <testdoxHtml outputFile="build/logs/testdox.html"/> + <testdoxText outputFile="build/logs/testdox.txt"/> + <junit outputFile="build/logs/logfile.xml"/> + </logging> + <source> + <include> + <directory suffix=".php">./app</directory> + </include> + <exclude> + <directory suffix=".php">./app/Views</directory> + <file>./app/Config/Routes.php</file> + </exclude> + </source> + <php> + <server name="app.baseURL" value="http://example.com/"/> + <server name="CODEIGNITER_SCREAM_DEPRECATIONS" value="0"/> + <!-- Directory containing phpunit.xml --> + <const name="HOMEPATH" value="./"/> + <!-- Directory containing the Paths config file --> + <const name="CONFIGPATH" value="./app/Config/"/> + <!-- Directory containing the front controller (index.php) --> + <const name="PUBLICPATH" value="./public/"/> + <!-- Database configuration --> + <!-- Uncomment to provide your own database for testing + <env name="database.tests.hostname" value="localhost"/> + <env name="database.tests.database" value="tests"/> + <env name="database.tests.username" value="tests_user"/> + <env name="database.tests.password" value=""/> + <env name="database.tests.DBDriver" value="MySQLi"/> + <env name="database.tests.DBPrefix" value="tests_"/> + --> + </php> </phpunit> 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 @@ +<IfModule authz_core_module> + Require all denied +</IfModule> +<IfModule !authz_core_module> + Deny from all +</IfModule> 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 @@ +<!DOCTYPE html> +<html> +<head> + <title>403 Forbidden</title> +</head> +<body> + +<p>Directory access is forbidden.</p> + +</body> +</html> 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", 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: 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 @@ <output>api/build/</output> <cache>api/cache/</cache> </paths> - <version number="4.5.0"> + <version number="4.5.1"> <api format="php"> <source dsn="."> <path>system</path> diff --git a/phpstan-baseline.php b/phpstan-baseline.php index ffe358b48943..cfee07815e8a 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, @@ -4141,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, @@ -4466,11 +4441,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, @@ -5356,16 +5326,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, - '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, @@ -7431,11 +7391,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, @@ -8646,16 +8601,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, @@ -9756,36 +9701,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, @@ -10046,26 +9961,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, @@ -10481,11 +10376,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, @@ -10511,26 +10401,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, @@ -11086,11 +10956,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, @@ -11176,26 +11041,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, @@ -11286,36 +11131,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, @@ -11451,11 +11266,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, @@ -11466,11 +11276,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, @@ -11571,16 +11376,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, @@ -11611,16 +11406,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, @@ -11666,16 +11451,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, @@ -11716,16 +11491,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, @@ -11866,71 +11631,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, @@ -11946,11 +11651,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\\<Config\\\\TestRegistrar\\>, string given\\.$#', 'count' => 1, @@ -12276,31 +11976,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, @@ -12466,11 +12141,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\\|string\\>\\|string, array\\<int, string\\> given\\.$#', 'count' => 2, @@ -12547,39 +12217,19 @@ 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:testDisableNumberNative\\(\\) has no return type specified\\.$#', + 'message' => '#^Property CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:\\$tests has no 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', + 'message' => '#^Class stdClass referenced with incorrect case\\: stdclass\\.$#', + 'count' => 9, + 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/RawSqlTest.php', ]; $ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\Database\\\\Live\\\\MySQLi\\\\NumberNativeTest\\:\\:testQueryDataAfterDisableNumberNative\\(\\) has no return type specified\\.$#', + 'message' => '#^Call to an undefined method CodeIgniter\\\\Database\\\\BaseConnection\\:\\:getCursor\\(\\)\\.$#', '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, - 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/NumberNativeTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Class stdClass referenced with incorrect case\\: stdclass\\.$#', - 'count' => 9, - 'path' => __DIR__ . '/tests/system/Database/Live/MySQLi/RawSqlTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Call to an undefined method CodeIgniter\\\\Database\\\\BaseConnection\\:\\:getCursor\\(\\)\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/Database/Live/OCI8/CallStoredProcedureTest.php', + 'path' => __DIR__ . '/tests/system/Database/Live/OCI8/CallStoredProcedureTest.php', ]; $ignoreErrors[] = [ 'message' => '#^Call to an undefined method CodeIgniter\\\\Database\\\\BaseConnection\\:\\:storedProcedure\\(\\)\\.$#', @@ -12851,21 +12501,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, @@ -13081,21 +12716,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, @@ -13221,56 +12841,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, - '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' => '#^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, - '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, - 'path' => __DIR__ . '/tests/system/HTTP/CURLRequestTest.php', -]; $ignoreErrors[] = [ 'message' => '#^Assigning \'10\' directly on offset \'HTTP_CONTENT_LENGTH\' of \\$_SERVER is discouraged\\.$#', 'count' => 1, @@ -13291,26 +12861,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\\\\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, @@ -13331,16 +12881,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, @@ -13681,11 +13221,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\\<string, string\\>\\) does not accept array\\<int, string\\>\\.$#', 'count' => 1, @@ -14011,101 +13546,6 @@ 'count' => 1, 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testDefault\\(\\) has no return type specified\\.$#', - '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', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testExtensionPHP\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.php', -]; -$ignoreErrors[] = [ - 'message' => '#^Method CodeIgniter\\\\HTTP\\\\SiteURIFactoryDetectRoutePathTest\\:\\:testPathInfoSubfolder\\(\\) has no return type specified\\.$#', - 'count' => 1, - 'path' => __DIR__ . '/tests/system/HTTP/SiteURIFactoryDetectRoutePathTest.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, @@ -14156,26 +13596,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, @@ -14196,116 +13616,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, @@ -14381,21 +13701,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, @@ -14571,31 +13876,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, @@ -14956,31 +14241,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, @@ -15041,11 +14301,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, @@ -15061,11 +14316,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, @@ -15991,71 +15241,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, @@ -16081,11 +15266,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, @@ -16101,11 +15281,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, @@ -16116,16 +15291,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, @@ -16246,21 +15411,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, @@ -16416,11 +15566,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, @@ -16466,11 +15611,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, @@ -16691,21 +15831,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, @@ -16866,56 +15991,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, @@ -17636,11 +16711,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, diff --git a/phpunit.xml.dist b/phpunit.xml.dist index 45b6b07231c4..7464323e4078 100644 --- a/phpunit.xml.dist +++ b/phpunit.xml.dist @@ -1,11 +1,20 @@ <?xml version="1.0" encoding="UTF-8"?> -<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd" - bootstrap="system/Test/bootstrap.php" backupGlobals="false" - beStrictAboutOutputDuringTests="true" colors="true" columns="max" - failOnRisky="true" failOnWarning="true" - cacheDirectory=".phpunit.cache"> - <coverage ignoreDeprecatedCodeUnits="true"> +<phpunit + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd" + bootstrap="system/Test/bootstrap.php" + backupGlobals="false" + beStrictAboutOutputDuringTests="true" + colors="true" + columns="max" + failOnRisky="true" + failOnWarning="true" + cacheDirectory="build/.phpunit.cache"> + <coverage + includeUncoveredFiles="true" + pathCoverage="false" + ignoreDeprecatedCodeUnits="true" + disableCodeCoverageIgnore="true"> <report> <clover outputFile="build/logs/clover.xml"/> <html outputDirectory="build/coverage/html" highLowerBound="80"/> 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<class-string> + */ + 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; } } 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); } /** diff --git a/system/CLI/BaseCommand.php b/system/CLI/BaseCommand.php index 1b273846bd74..86ba504feaa6 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<int|string, string|null> $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<string, string> $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 array<string, string>|Commands|LoggerInterface|string|null */ public function __get(string $key) { 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/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/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) { 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]); diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index e0bd7bb51217..b597c6d6cd10 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) . "'"; } @@ -1328,8 +1332,8 @@ public function escape($str) /** * Escape String * - * @param list<string>|string $str Input string - * @param bool $like Whether or not the string will be used in a LIKE condition + * @param list<string|Stringable>|string|Stringable $str Input string + * @param bool $like Whether the string will be used in a LIKE condition * * @return list<string>|string */ @@ -1343,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 @@ -1371,7 +1383,7 @@ public function escapeString($str, bool $like = false) * Calls the individual driver for platform * specific escaping for LIKE conditions * - * @param list<string>|string $str + * @param list<string|Stringable>|string|Stringable $str * * @return list<string>|string */ 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); } 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); } diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index c631e4162da4..115016225062 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 */ @@ -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 @@ -433,7 +434,7 @@ public function prepare(?RequestInterface $request = null, ?ResponseInterface $r . $kintScript . PHP_EOL; - if (str_contains($response->getBody(), '<head>')) { + if (str_contains((string) $response->getBody(), '<head>')) { $response->setBody( preg_replace( '/<head>/', diff --git a/system/Debug/Toolbar/Collectors/Routes.php b/system/Debug/Toolbar/Collectors/Routes.php index 737c86bff692..b6862dcee73c 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<array{ + * directory: string, + * controller: string, + * method: string, + * paramCount: int, + * truePCount: int, + * params: list<array{ + * name: string, + * value: mixed + * }> + * }>, + * routes: list<array{ + * method: string, + * route: string, + * handler: string + * }> + * } + * * @throws ReflectionException */ public function display(): array diff --git a/system/Debug/Toolbar/Views/toolbar.css b/system/Debug/Toolbar/Views/toolbar.css index 4154f4c5c4ca..2e165b825e99 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; @@ -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; diff --git a/system/HTTP/CURLRequest.php b/system/HTTP/CURLRequest.php index 725195918209..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<string, mixed> $options */ public function __construct(App $config, URI $uri, ?ResponseInterface $response = null, array $options = []) { @@ -116,7 +118,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); + // Remove the default Content-Type header. + $this->responseOrig->removeHeader('Content-Type'); + $this->baseURI = $uri->useRawQueryString(); $this->defaultOptions = $options; 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/system/I18n/Time.php b/system/I18n/Time.php index 2c6f3c4fab70..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 @@ -21,26 +22,26 @@ * * 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 */ -class Time extends DateTimeImmutable +class Time extends DateTimeImmutable implements Stringable { use TimeTrait; } 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<int|string, bool|null>, data: row_array}|array{} */ protected $tempData = []; diff --git a/system/Test/Interfaces/FabricatorModel.php b/system/Test/Interfaces/FabricatorModel.php index d4a4c270919c..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<int|string>|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<row_array|object>) */ public function find($id = null); @@ -44,14 +47,15 @@ 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 * * @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 diff --git a/system/View/Plugins.php b/system/View/Plugins.php index da147d097d06..7142e44c452e 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{email?: string, title?: string, attributes?: array<string, string>|object|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?: array<string, string>|object|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 array<int|string, string>|list<string> $params */ public static function lang(array $params = []): string { @@ -76,8 +82,10 @@ 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 + public static function validationErrors(array $params = []): string { $validator = service('validation'); if ($params === []) { @@ -90,6 +98,8 @@ public static function ValidationErrors(array $params = []): string /** * Wrap helper function to use as view plugin. * + * @param list<string> $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 list<string> $params */ public static function siteURL(array $params = []): string { diff --git a/tests/_support/Config/Registrar.php b/tests/_support/Config/Registrar.php index 8889021a2d00..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<string, array<string, array<string, bool|int|string>|bool|int|string>> */ - protected static $dbConfig = [ + protected static array $dbConfig = [ 'MySQLi' => [ 'DSN' => '', 'hostname' => '127.0.0.1', @@ -126,15 +126,15 @@ class Registrar /** * Override database config * - * @return array + * @return array<string, array<string, bool|int|string>|bool|int|string> */ - public static function Database() + public static function Database(): array { $config = []; // 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]; } @@ -146,9 +146,9 @@ public static function Database() * * @see PublisherRestrictionsTest::testRegistrarsNotAllowed() * - * @return array + * @return array<string, array<string, string>> */ - public static function Publisher() + public static function Publisher(): array { return [ 'restrictions' => [SUPPORTPATH => '*'], 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(), 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/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); } } 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..dfca8511ada5 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', @@ -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'); @@ -447,7 +460,7 @@ public function testSetComponentInstances(array $data) /** * @depends testSetComponentInstances */ - public function testIsUpdated(array $data) + public function testIsUpdated(array $data): void { Factories::reset(); @@ -466,21 +479,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/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index e1b700547c0c..0f931cdbe85c 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'"; @@ -62,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 '!'"; @@ -70,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') { 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 deleted file mode 100644 index f6e06a882191..000000000000 --- a/tests/system/HTTP/CURLRequestDoNotShareOptionsTest.php +++ /dev/null @@ -1,1144 +0,0 @@ -<?php - -declare(strict_types=1); - -/** - * This file is part of CodeIgniter 4 framework. - * - * (c) CodeIgniter Foundation <admin@codeigniter.com> - * - * For the full copyright and license information, please view - * the LICENSE file that was distributed with this source code. - */ - -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; - -/** - * @internal - * - * @group Others - */ -final class CURLRequestDoNotShareOptionsTest extends CIUnitTestCase -{ - private CURLRequest $request; - - protected function setUp(): void - { - parent::setUp(); - - Services::reset(); - $this->request = $this->getRequest(); - } - - protected function getRequest(array $options = []) - { - $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); - $app = new App(); - - $config = new ConfigCURLRequest(); - $config->shareOptions = false; - Factories::injectMock('config', 'CURLRequest', $config); - - 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 - { - $_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]); - } - - 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 - */ - 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]); - } - - public function testRequestMethodGetsSanitized(): void - { - $this->request->request('<script>Custom</script>', '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\x0a<title>Update success! config</title>"; - - $this->request->setOutput($output); - - $response = $this->request->request('get', 'http://example.com', [ - 'auth' => [ - 'username', - 'password', - 'digest', - ], - ]); - - $options = $this->request->curl_options; - - $this->assertSame('<title>Update success! config</title>', $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\x0a<title>Update success! config</title>"; - - $this->request->setOutput($output); - - $response = $this->request->setAuth('username', 'password', 'digest')->get('http://example.com'); - - $options = $this->request->curl_options; - - $this->assertSame('<title>Update success! config</title>', $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 testSSLWithBadKey(): void - { - $file = 'something_obviously_bogus'; - $this->expectException(HTTPException::class); - - $this->request->request('get', 'http://example.com', [ - 'verify' => $file, - ]); - } - - public function testProxyuOption() - { - $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\x0a<title>Update success! config</title>"; - $request->setOutput($output); - - $response = $request->get('answer'); - - $this->assertSame('<title>Update success! config</title>', $response->getBody()); - - $responseHeaderKeys = [ - 'Cache-Control', - 'Content-Type', - 'Server', - 'Connection', - 'Keep-Alive', - 'Set-Cookie', - 'Date', - 'Expires', - 'Pragma', - 'Transfer-Encoding', - ]; - $this->assertSame($responseHeaderKeys, array_keys($response->headers())); - - $this->assertSame(200, $response->getStatusCode()); - } - - /** - * 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\x0a<title>Hello1</title>"; - $request->setOutput($output); - - $response = $request->get('answer1'); - - $this->assertSame('<title>Hello1</title>', $response->getBody()); - - $responseHeaderKeys = [ - 'Cache-Control', - 'Content-Type', - 'Server', - 'Expires', - 'Pragma', - '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\x0a<title>Hello2</title>"; - $request->setOutput($output); - - $response = $request->get('answer2'); - - $this->assertSame('<title>Hello2</title>', $response->getBody()); - - $responseHeaderKeys = [ - 'Cache-Control', - 'Content-Type', - 'Expires', - '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 - { - $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 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([ - '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] - ); - } - - 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( - '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 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]); - } -} diff --git a/tests/system/HTTP/CURLRequestShareOptionsTest.php b/tests/system/HTTP/CURLRequestShareOptionsTest.php new file mode 100644 index 000000000000..bb0216466787 --- /dev/null +++ b/tests/system/HTTP/CURLRequestShareOptionsTest.php @@ -0,0 +1,76 @@ +<?php + +declare(strict_types=1); + +/** + * This file is part of CodeIgniter 4 framework. + * + * (c) CodeIgniter Foundation <admin@codeigniter.com> + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\HTTP; + +use CodeIgniter\Config\Factories; +use CodeIgniter\Test\Mock\MockCURLRequest; +use Config\App; +use Config\CURLRequest as ConfigCURLRequest; + +/** + * This test case is for the case where shareOptions is true. + * The shareOptions should be set to false. + * + * @internal + * + * @group Others + */ +final class CURLRequestShareOptionsTest extends CURLRequestTest +{ + protected function getRequest(array $options = []): MockCURLRequest + { + $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); + $app = new App(); + + $config = new ConfigCURLRequest(); + $config->shareOptions = true; + Factories::injectMock('config', 'CURLRequest', $config); + + return new MockCURLRequest(($app), $uri, new Response($app), $options); + } + + 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'); + + // The Content-Length header is shared! + $this->assertSame('9', $request->header('Content-Length')->getValue()); + } + + 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'); + + // 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 6b51b4d585f4..1f53a57a8465 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 CURLRequest $request; + protected MockCURLRequest $request; protected function setUp(): void { @@ -39,13 +41,16 @@ protected function setUp(): void $this->request = $this->getRequest(); } - protected function getRequest(array $options = []) + /** + * @param array<string, mixed> $options + */ + protected function getRequest(array $options = []): MockCURLRequest { $uri = isset($options['base_uri']) ? new URI($options['base_uri']) : new URI(); $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); @@ -205,7 +210,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], @@ -226,6 +231,23 @@ public function testOptionsAreSharedBetweenRequests(): 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 */ @@ -387,20 +409,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\x0a<title>Update success! config</title>"; +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\x0a<title>Update success! config</title>"; $this->request->setOutput($output); @@ -440,20 +462,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\x0a<title>Update success! config</title>"; +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\x0a<title>Update success! config</title>"; $this->request->setOutput($output); @@ -560,7 +582,7 @@ public function testSSLWithBadKey(): void ]); } - public function testProxyuOption() + public function testProxyuOption(): void { $this->request->request('get', 'http://example.com', [ 'proxy' => 'http://localhost:3128', @@ -782,7 +804,6 @@ public function testSendContinuedWithManyHeaders(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Server', 'Connection', 'Keep-Alive', @@ -790,6 +811,7 @@ public function testSendContinuedWithManyHeaders(): void 'Date', 'Expires', 'Pragma', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -836,10 +858,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 +881,8 @@ public function testResponseHeadersWithMultipleRequests(): void $responseHeaderKeys = [ 'Cache-Control', - 'Content-Type', 'Expires', + 'Content-Type', 'Transfer-Encoding', ]; $this->assertSame($responseHeaderKeys, array_keys($response->headers())); @@ -868,6 +890,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([ @@ -911,6 +965,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([ @@ -1026,7 +1095,10 @@ public function testJSONData(): void $this->assertSame('POST', $this->request->getMethod()); $expected = json_encode($params); - $this->assertSame($expected, $this->request->getBody()); + $this->assertSame( + $expected, + $this->request->curl_options[CURLOPT_POSTFIELDS] + ); } public function testSetJSON(): void @@ -1040,7 +1112,11 @@ 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( 'Content-Type: application/json', $this->request->curl_options[CURLOPT_HTTPHEADER][0] @@ -1137,4 +1213,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')); + } } 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 2ee32da768fc..b623068943fe 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 = <<<EOH - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> - <input type="hidden" name="{$Name}" value="{$Value}" style="display:none;"> + $expected = <<<'EOH' + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> + + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $this->assertSame($expected, form_open('foo/bar', $attributes)); + } - EOH; - } else { - $expected = <<<'EOH' - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> + public function testFormOpenBasicWithCsrf(): void + { + $this->setRequest(); + $this->setCsrfFilter(); - EOH; - } + $value = csrf_hash(); + $name = csrf_token(); + $expected = <<<EOH + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> + <input type="hidden" name="{$name}" value="{$value}"> + EOH; $attributes = [ 'name' => 'form', @@ -101,21 +116,29 @@ 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 = <<<EOH - <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8"> - <input type="hidden" name="{$Name}" value="{$Value}" style="display:none;"> - - EOH; - } else { - $expected = <<<'EOH' - <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8"> - - EOH; - } + $expected = <<<'EOH' + <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8"> + + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $this->assertSame($expected, form_open('', $attributes)); + } + + public function testFormOpenWithoutActionWithCsrf(): void + { + $this->setRequest(); + $this->setCsrfFilter(); + + $value = csrf_hash(); + $name = csrf_token(); + $expected = <<<EOH + <form action="http://example.com/index.php" name="form" id="form" method="POST" accept-charset="utf-8"> + <input type="hidden" name="{$name}" value="{$value}"> + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', @@ -128,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 = <<<EOH - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="post" accept-charset="utf-8"> - <input type="hidden" name="{$Name}" value="{$Value}" style="display:none;"> + $expected = <<<'EOH' + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="post" accept-charset="utf-8"> - EOH; - } else { - $expected = <<<'EOH' - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="post" accept-charset="utf-8"> + EOH; - EOH; - } + $attributes = [ + 'name' => 'form', + 'id' => 'form', + ]; + $this->assertSame($expected, form_open('foo/bar', $attributes)); + } + public function testFormOpenWithoutMethodWithCsrf(): void + { + $this->setRequest(); + $this->setCsrfFilter(); + + $value = csrf_hash(); + $name = csrf_token(); + $expected = <<<EOH + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="post" accept-charset="utf-8"> + <input type="hidden" name="{$name}" value="{$value}"> + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', @@ -155,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 = <<<EOH - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> - <input type="hidden" name="foo" value="bar"> - <input type="hidden" name="{$Name}" value="{$Value}"> + $expected = <<<'EOH' + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> - EOH; - } else { - $expected = <<<'EOH' - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> + <input type="hidden" name="foo" value="bar"> - <input type="hidden" name="foo" value="bar"> + EOH; + $attributes = [ + 'name' => 'form', + 'id' => 'form', + 'method' => 'POST', + ]; + $hidden = [ + 'foo' => 'bar', + ]; + $this->assertSame($expected, form_open('foo/bar', $attributes, $hidden)); + } - EOH; - } + public function testFormOpenWithHiddenWithCsrf(): void + { + $this->setRequest(); + $this->setCsrfFilter(); + + $value = csrf_hash(); + $name = csrf_token(); + $expected = <<<EOH + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" accept-charset="utf-8"> + <input type="hidden" name="{$name}" value="{$value}"> + <input type="hidden" name="foo" value="bar"> + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', @@ -189,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 - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" enctype="multipart/form-data" accept-charset="utf-8"> - <input type="hidden" name="{$Name}" value="{$Value}" style="display:none;"> - - EOH; - } else { - $expected = <<<'EOH' - <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" enctype="multipart/form-data" accept-charset="utf-8"> - - EOH; - } + $expected = <<<'EOH' + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" enctype="multipart/form-data" accept-charset="utf-8"> + + 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 + <form action="http://example.com/index.php/foo/bar" name="form" id="form" method="POST" enctype="multipart/form-data" accept-charset="utf-8"> + <input type="hidden" name="{$name}" value="{$value}"> + EOH; $attributes = [ 'name' => 'form', 'id' => 'form', @@ -267,7 +320,7 @@ public function testFormInput(): void $this->assertSame($expected, form_input($data)); } - public function testFormInputXHTML(): void + public function testFormInputXhtml(): void { $this->disableHtml5(); @@ -287,14 +340,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); @@ -332,7 +385,7 @@ public function testFormUpload(): void $this->assertSame($expected, form_upload('attachment')); } - public function testFormUploadXHTML(): void + public function testFormUploadXhtml(): void { $this->disableHtml5(); @@ -668,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(); 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/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 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('<p>Third</p>', $content); } - public function testRenderSectionSavingData() + public function testRenderSectionSavingData(): void { $view = new View($this->config, $this->viewsDir, $this->loader); $expected = "<title>Welcome to CodeIgniter 4!</title>\n<h1>Welcome to CodeIgniter 4!</h1>\n<p>Hello World</p>"; 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..c2407f651ae1 --- /dev/null +++ b/user_guide_src/source/changelogs/v4.5.1.rst @@ -0,0 +1,19 @@ +############# +Version 4.5.1 +############# + +Release Date: April 14, 2024 + +**4.5.1 release of CodeIgniter4** + +.. contents:: + :local: + :depth: 3 + +********** +Bugs Fixed +********** + +See the repo's +`CHANGELOG.md <https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md>`_ +for a complete list of 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/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', // ... ]; 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 <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 diff --git a/user_guide_src/source/incoming/routing.rst b/user_guide_src/source/incoming/routing.rst index 77da04253bff..2515d1a888b9 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 @@ -815,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. @@ -919,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) ============================ diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index 7096c3d6fb73..3dd4c2a6a1b7 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:: 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 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 + Initial Configuration --------------------- @@ -82,7 +111,29 @@ Whenever there is a new release, then from the command line in your project root composer update -Read the :doc:`upgrade instructions <upgrading>`, and check Breaking Changes and Enhancements. +Read the :doc:`upgrade instructions <upgrading>` and :doc:`change log <../changelogs/index>`, +and check Breaking Changes and Enhancements. + +Upgrading to a Specified Version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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: + +.. code-block:: text + + "require": { + ... + "codeigniter4/framework": "4.4.8" + }, + +Then, run the ``composer update`` command. + +.. 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 to the latest version. See `Writing Version Constraints`_ for how to specify the version. Pros ---- @@ -215,7 +266,25 @@ Whenever there is a new release, then from the command line in your project root composer update -Read the :doc:`upgrade instructions <upgrading>`, and check Breaking Changes and Enhancements. +Read the :doc:`upgrade instructions <upgrading>` and :doc:`change log <../changelogs/index>`, +and check Breaking Changes and Enhancements. + +Upgrading to a Specified Version +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +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: + +.. code-block:: text + + "require": { + ... + "codeigniter4/framework": "4.4.8" + }, + +Then, run the ``composer update`` command. 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 <upgrading>`, and check Breaking Changes and Enhancements. +Read the :doc:`upgrade instructions <upgrading>` and :doc:`change log <../changelogs/index>`, +and check Breaking Changes and Enhancements. Pros ==== 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 diff --git a/user_guide_src/source/installation/upgrade_450.rst b/user_guide_src/source/installation/upgrade_450.rst index 09a6b16d15b1..3c4cdc4eddbe 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: @@ -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 <v450-removed-deprecated-items>` 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 <v450-removed-deprecated-items>` +for details. Breaking Enhancements ********************* @@ -322,6 +323,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 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..2900209474f0 --- /dev/null +++ b/user_guide_src/source/installation/upgrade_451.rst @@ -0,0 +1,38 @@ +############################# +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 <app-starter-upgrading>` +- :ref:`Composer Installation Adding CodeIgniter4 to an Existing Project Upgrading <adding-codeigniter4-upgrading>` +- :ref:`Manual Installation Upgrading <installing-manual-upgrading>` + +.. contents:: + :local: + :depth: 2 + +************* +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 <https://packagist.org/explore/?query=codeigniter4%20updates>`_. + +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: + +- .gitignore +- composer.json +- phpunit.xml.dist +- tests/.htaccess +- tests/index.html +- writable/debugbar/.gitkeep (Removed) +- writable/debugbar/index.html +- writable/index.html 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 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. + } + // ... } 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 { 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 @@ +<!DOCTYPE html> +<html> +<head> + <title>403 Forbidden</title> +</head> +<body> + +<p>Directory access is forbidden.</p> + +</body> +</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 @@ +<!DOCTYPE html> +<html> +<head> + <title>403 Forbidden</title> +</head> +<body> + +<p>Directory access is forbidden.</p> + +</body> +</html>