diff --git a/CHANGELOG.md b/CHANGELOG.md index 60e6e3b4ed00..74b2f56755c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,21 @@ # Changelog +## [v4.3.1](https://github.com/codeigniter4/CodeIgniter4/tree/v4.3.1) (2023-01-14) +[Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.3.0...v4.3.1) + +### Fixed Bugs + +* fix: Email config in the .env doesn't appear as expected by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7078 +* fix: TypeError in Validation is_unique/is_not_unique by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7085 +* fix: revert method name resetQuery() changed accidentally by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7083 +* fix: handling float in Validation Strcit Rules (greater_than, greater_than_equal_to, less_than, less_than_equal_to) by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7098 +* docs: add missing instruction for Config/Exceptions in PHP 8.2 by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7100 +* fix: Call to undefined method Composer\InstalledVersions::getAllRawData() error by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/7107 + +### Refactoring + +* [Rector] Enable AddDefaultValueForUndefinedVariableRector by @samsonasik in https://github.com/codeigniter4/CodeIgniter4/pull/7088 + ## [v4.3.0](https://github.com/codeigniter4/CodeIgniter4/tree/v4.3.0) (2023-01-10) [Full Changelog](https://github.com/codeigniter4/CodeIgniter4/compare/v4.2.12...v4.3.0) @@ -12,7 +28,6 @@ * fix: exceptionHandler may return invalid HTTP status code by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6228 * feat: add Form helpers for Validation Errors by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6384 * fix: ValidationInterface by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6253 -* [Reverted] Make Unique Index Name Unique by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6516 * fix: types in database classes by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6527 * fix: ResponseInterface (1) by @kenjis in https://github.com/codeigniter4/CodeIgniter4/pull/6556 * Improve BaseConnection::getForeignKeyData() and Forge::addForeignKey() by @sclubricants in https://github.com/codeigniter4/CodeIgniter4/pull/6468 diff --git a/admin/RELEASE.md b/admin/RELEASE.md index e5ab1b4d70ba..cfa7fe3bcdb6 100644 --- a/admin/RELEASE.md +++ b/admin/RELEASE.md @@ -2,9 +2,17 @@ > Documentation guide based on the releases of `4.0.5` and `4.1.0` on January 31, 2021. > -> Updated for `4.2.10` on November 5, 2022. +> Updated for `4.3.0` on January 10, 2023. > -> -MGatner +> -MGatner, kenjis + +## [Minor version only] Merge minor version branch into develop + +If you release a new minor version. + +* Create PR to merge `4.x` into `develop` and merge it +* Delete the merged `4.x` branch (This closes all PRs to the branch) +* Do the regular release process. Go to the next "Changelog" section ## Changelog @@ -17,7 +25,20 @@ When generating the changelog each Pull Request to be included must have one of PRs with breaking changes must have the following additional label: - **breaking change** ... PRs that may break existing functionalities -To auto-generate, start drafting a new Release and use the "Generate release notes" button. +### Generate Changelog + +To auto-generate, navigate to the [Releases](https://github.com/codeigniter4/CodeIgniter4/releases) page, +click the "Draft a new release" button. + +* Tag: "v4.x.x" (Create new tag) +* Target: develop + +Click the "Generate release notes" button. + +Check the resulting content. If there are items in the *Others* section which +should be included in the changelog, add a label to the PR and regenerate +the changelog. + Copy the resulting content into **CHANGELOG.md** and adjust the format to match the existing content. ## Preparation @@ -73,9 +94,9 @@ cd release-test composer test && composer info codeigniter4/framework ``` * Verify that the user guide actions succeeded: - * "Deploy Distributable Repos", framework repo - * "Deploy Production", UG repo - * "pages-build-deployment", UG repo + * "[Deploy Distributable Repos](https://github.com/codeigniter4/CodeIgniter4/actions/workflows/deploy-distributables.yml)", the main repo + * "[Deploy Production](https://github.com/codeigniter4/userguide/actions/workflows/deploy.yml)", UG repo + * "[pages-build-deployment](https://github.com/codeigniter4/userguide/actions/workflows/pages/pages-build-deployment)", UG repo * Fast-forward `develop` branch to catch the merge commit from `master` ```console git fetch origin @@ -92,6 +113,13 @@ git merge origin/4.x git merge origin/develop git push origin HEAD ``` +* [Minor version only] Create the next minor upgrade branch `4.x`: +```console +git fetch origin +git switch develop +git switch -c 4.x +git push origin HEAD +``` * Publish any Security Advisories that were resolved from private forks * Announce the release on the forums and Slack channel (note: this forum is restricted to administrators): * Make a new topic in the "News & Discussion" forums: https://forum.codeigniter.com/forum-2.html diff --git a/admin/next-changelog-minor.rst b/admin/next-changelog-minor.rst index 310dffdeafa2..f5bb20004d77 100644 --- a/admin/next-changelog-minor.rst +++ b/admin/next-changelog-minor.rst @@ -71,4 +71,6 @@ Deprecations Bugs Fixed ********** -See the repo's `CHANGELOG.md `_ for a complete list of bugs fixed. +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/admin/next-changelog-patch.rst b/admin/next-changelog-patch.rst index 2761f6b90434..4c76ca01a112 100644 --- a/admin/next-changelog-patch.rst +++ b/admin/next-changelog-patch.rst @@ -12,9 +12,6 @@ Release Date: Unreleased BREAKING ******** -Enhancements -************ - Message Changes *************** @@ -27,4 +24,6 @@ Deprecations Bugs Fixed ********** -See the repo's `CHANGELOG.md `_ for a complete list of bugs fixed. +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/app/Config/Email.php b/app/Config/Email.php index 729e8957f9ab..01350186a3e9 100644 --- a/app/Config/Email.php +++ b/app/Config/Email.php @@ -6,9 +6,9 @@ class Email extends BaseConfig { - public string $fromEmail; - public string $fromName; - public string $recipients; + public string $fromEmail = ''; + public string $fromName = ''; + public string $recipients = ''; /** * The "user agent" @@ -28,17 +28,17 @@ class Email extends BaseConfig /** * SMTP Server Address */ - public string $SMTPHost; + public string $SMTPHost = ''; /** * SMTP Username */ - public string $SMTPUser; + public string $SMTPUser = ''; /** * SMTP Password */ - public string $SMTPPass; + public string $SMTPPass = ''; /** * SMTP Port diff --git a/composer.json b/composer.json index 50bd5e6dacac..682e3f9c81c4 100644 --- a/composer.json +++ b/composer.json @@ -25,7 +25,7 @@ "phpunit/phpcov": "^8.2", "phpunit/phpunit": "^9.1", "predis/predis": "^1.1 || ^2.0", - "rector/rector": "0.15.2", + "rector/rector": "0.15.5", "vimeo/psalm": "^5.0" }, "suggest": { diff --git a/phpstan-baseline.neon.dist b/phpstan-baseline.neon.dist index 986601771fef..af189e08b8b1 100644 --- a/phpstan-baseline.neon.dist +++ b/phpstan-baseline.neon.dist @@ -25,11 +25,6 @@ parameters: count: 1 path: system/Cache/Handlers/MemcachedHandler.php - - - message: "#^Variable \\$data might not be defined\\.$#" - count: 1 - path: system/Cache/Handlers/MemcachedHandler.php - - message: "#^Property CodeIgniter\\\\Cache\\\\Handlers\\\\RedisHandler\\:\\:\\$redis \\(Redis\\) in isset\\(\\) is not nullable\\.$#" count: 1 @@ -200,11 +195,6 @@ parameters: count: 1 path: system/Helpers/number_helper.php - - - message: "#^Variable \\$count might not be defined\\.$#" - count: 1 - path: system/Helpers/url_helper.php - - message: "#^Property CodeIgniter\\\\Images\\\\Handlers\\\\BaseHandler\\:\\:\\$image \\(CodeIgniter\\\\Images\\\\Image\\) in empty\\(\\) is not falsy\\.$#" count: 1 @@ -230,21 +220,6 @@ parameters: count: 4 path: system/Images/Handlers/ImageMagickHandler.php - - - message: "#^Variable \\$gravity might not be defined\\.$#" - count: 1 - path: system/Images/Handlers/ImageMagickHandler.php - - - - message: "#^Variable \\$xAxis might not be defined\\.$#" - count: 1 - path: system/Images/Handlers/ImageMagickHandler.php - - - - message: "#^Variable \\$yAxis might not be defined\\.$#" - count: 1 - path: system/Images/Handlers/ImageMagickHandler.php - - message: "#^Call to an undefined method CodeIgniter\\\\Router\\\\RouteCollectionInterface\\:\\:getDefaultNamespace\\(\\)\\.$#" count: 3 diff --git a/rector.php b/rector.php index d53f9af118eb..095cb2444c62 100644 --- a/rector.php +++ b/rector.php @@ -36,7 +36,6 @@ use Rector\EarlyReturn\Rector\If_\RemoveAlwaysElseRector; use Rector\EarlyReturn\Rector\Return_\PreparedValueToEarlyReturnRector; use Rector\Php55\Rector\String_\StringClassNameToClassConstantRector; -use Rector\Php56\Rector\FunctionLike\AddDefaultValueForUndefinedVariableRector; use Rector\Php70\Rector\FuncCall\RandomFunctionRector; use Rector\Php71\Rector\FuncCall\CountOnNullRector; use Rector\Php73\Rector\FuncCall\JsonThrowOnErrorRector; @@ -106,9 +105,6 @@ // sometime too detail CountOnNullRector::class, - // may not be unitialized on purpose - AddDefaultValueForUndefinedVariableRector::class, - // use mt_rand instead of random_int on purpose on non-cryptographically random RandomFunctionRector::class, diff --git a/system/Autoloader/Autoloader.php b/system/Autoloader/Autoloader.php index 0041937c78d1..0f1d91eb7809 100644 --- a/system/Autoloader/Autoloader.php +++ b/system/Autoloader/Autoloader.php @@ -373,6 +373,14 @@ private function loadComposerNamespaces(ClassLoader $composer, array $composerPa unset($namespacePaths['CodeIgniter\\']); } + if (! method_exists(InstalledVersions::class, 'getAllRawData')) { + throw new RuntimeException( + 'Your Composer version is too old.' + . ' Please update Composer (run `composer self-update`) to v2.0.14 or later' + . ' and remove your vendor/ directory, and run `composer update`.' + ); + } + // This method requires Composer 2.0.14 or later. $packageList = InstalledVersions::getAllRawData()[0]['versions']; // Check config for $composerPackages. diff --git a/system/Cache/Handlers/MemcachedHandler.php b/system/Cache/Handlers/MemcachedHandler.php index f7d5ec8bcd1a..5053b1a6752a 100644 --- a/system/Cache/Handlers/MemcachedHandler.php +++ b/system/Cache/Handlers/MemcachedHandler.php @@ -124,7 +124,8 @@ public function initialize() */ public function get(string $key) { - $key = static::validateKey($key, $this->prefix); + $data = []; + $key = static::validateKey($key, $this->prefix); if ($this->memcached instanceof Memcached) { $data = $this->memcached->get($key); diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index 43f4caad61ea..5cb98c438863 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -47,7 +47,7 @@ class CodeIgniter /** * The current version of CodeIgniter Framework */ - public const CI_VERSION = '4.3.0'; + public const CI_VERSION = '4.3.1'; /** * App startup time. diff --git a/system/Commands/Generators/MigrationGenerator.php b/system/Commands/Generators/MigrationGenerator.php index 5cc3b6dfd56a..817c16885205 100644 --- a/system/Commands/Generators/MigrationGenerator.php +++ b/system/Commands/Generators/MigrationGenerator.php @@ -97,6 +97,7 @@ public function run(array $params) */ protected function prepare(string $class): string { + $data = []; $data['session'] = false; if ($this->getOption('session')) { diff --git a/system/Commands/Generators/SessionMigrationGenerator.php b/system/Commands/Generators/SessionMigrationGenerator.php index a1e02a131b63..fbfb2d3db1ff 100644 --- a/system/Commands/Generators/SessionMigrationGenerator.php +++ b/system/Commands/Generators/SessionMigrationGenerator.php @@ -89,6 +89,7 @@ public function run(array $params) */ protected function prepare(string $class): string { + $data = []; $data['session'] = true; $data['table'] = $this->getOption('t'); $data['DBGroup'] = $this->getOption('g'); diff --git a/system/Commands/Utilities/FilterCheck.php b/system/Commands/Utilities/FilterCheck.php index 15f66e97a8a7..d2eb2fb728a4 100644 --- a/system/Commands/Utilities/FilterCheck.php +++ b/system/Commands/Utilities/FilterCheck.php @@ -72,6 +72,7 @@ class FilterCheck extends BaseCommand */ public function run(array $params) { + $tbody = []; if (! isset($params[0], $params[1])) { CLI::error('You must specify a HTTP verb and a route.'); CLI::write(' Usage: ' . $this->usage); diff --git a/system/Database/BaseBuilder.php b/system/Database/BaseBuilder.php index 3142aa18d01b..9e2c634cb7f2 100644 --- a/system/Database/BaseBuilder.php +++ b/system/Database/BaseBuilder.php @@ -1423,6 +1423,7 @@ public function orHaving($key, $value = null, ?bool $escape = null) */ public function orderBy(string $orderBy, string $direction = '', ?bool $escape = null) { + $qbOrderBy = []; if (empty($orderBy)) { return $this; } @@ -3274,7 +3275,7 @@ protected function isLiteral(string $str): bool * * @return $this */ - public function resetQueryAsData() + public function resetQuery() { $this->resetSelect(); $this->resetWrite(); @@ -3456,7 +3457,7 @@ protected function setBind(string $key, $value = null, bool $escape = true): str */ protected function cleanClone() { - return (clone $this)->from([], true)->resetQueryAsData(); + return (clone $this)->from([], true)->resetQuery(); } /** diff --git a/system/Database/SQLSRV/Connection.php b/system/Database/SQLSRV/Connection.php index b74435036c18..5d9b208d6010 100755 --- a/system/Database/SQLSRV/Connection.php +++ b/system/Database/SQLSRV/Connection.php @@ -529,6 +529,7 @@ public function getPlatform(): string */ public function getVersion(): string { + $info = []; if (isset($this->dataCache['version'])) { return $this->dataCache['version']; } diff --git a/system/Debug/Exceptions.php b/system/Debug/Exceptions.php index 2670732d19d0..bcce589db894 100644 --- a/system/Debug/Exceptions.php +++ b/system/Debug/Exceptions.php @@ -80,6 +80,8 @@ public function __construct(ExceptionsConfig $config, $request, ResponseInterfac $this->response = $response; // workaround for upgraded users + // This causes "Deprecated: Creation of dynamic property" in PHP 8.2. + // @TODO remove this after dropping PHP 8.1 support. if (! isset($this->config->sensitiveDataInTrace)) { $this->config->sensitiveDataInTrace = []; } diff --git a/system/Debug/Toolbar.php b/system/Debug/Toolbar.php index 10dad0f4a947..17e67aa8eb94 100644 --- a/system/Debug/Toolbar.php +++ b/system/Debug/Toolbar.php @@ -76,6 +76,7 @@ public function __construct(ToolbarConfig $config) */ public function run(float $startTime, float $totalTime, RequestInterface $request, ResponseInterface $response): string { + $data = []; // Data items used within the view. $data['url'] = current_url(); $data['method'] = strtoupper($request->getMethod()); diff --git a/system/Debug/Toolbar/Collectors/Database.php b/system/Debug/Toolbar/Collectors/Database.php index 2991840c8de1..c7ed6703b402 100644 --- a/system/Debug/Toolbar/Collectors/Database.php +++ b/system/Debug/Toolbar/Collectors/Database.php @@ -140,6 +140,7 @@ protected function formatTimelineData(): array */ public function display(): array { + $data = []; $data['queries'] = array_map(static function (array $query) { $isDuplicate = $query['duplicate'] === true; diff --git a/system/Email/Email.php b/system/Email/Email.php index d113398d5dab..488a5ee76f04 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -1539,7 +1539,11 @@ public function send($autoClear = true) $this->setReplyTo($this->headers['From']); } - if (empty($this->recipients) && ! isset($this->headers['To']) && empty($this->BCCArray) && ! isset($this->headers['Bcc']) && ! isset($this->headers['Cc'])) { + if ( + empty($this->recipients) && ! isset($this->headers['To']) + && empty($this->BCCArray) && ! isset($this->headers['Bcc']) + && ! isset($this->headers['Cc']) + ) { $this->setErrorMessage(lang('Email.noRecipients')); return false; diff --git a/system/Helpers/html_helper.php b/system/Helpers/html_helper.php index 979aae1b9179..c7a36e270860 100755 --- a/system/Helpers/html_helper.php +++ b/system/Helpers/html_helper.php @@ -236,6 +236,7 @@ function link_tag( bool $indexPage = false, string $hreflang = '' ): string { + $attributes = []; // extract fields if needed if (is_array($href)) { $rel = $href['rel'] ?? $rel; diff --git a/system/Helpers/url_helper.php b/system/Helpers/url_helper.php index 1f2db240e627..682830ba1e5a 100644 --- a/system/Helpers/url_helper.php +++ b/system/Helpers/url_helper.php @@ -56,12 +56,10 @@ function _get_uri(string $relativePath = '', ?App $config = null): URI // Build the full URL based on $config and $relativePath $request = Services::request(); - if ($request instanceof CLIRequest) { - /** @var App $config */ - $url = rtrim($config->baseURL, '/ ') . '/'; - } else { - $url = $request->getUri()->getBaseURL(); - } + /** @var App $config */ + $url = $request instanceof CLIRequest + ? rtrim($config->baseURL, '/ ') . '/' + : $request->getUri()->getBaseURL(); // Check for an index page if ($config->indexPage !== '') { @@ -329,6 +327,7 @@ function mailto(string $email, string $title = '', $attributes = ''): string */ function safe_mailto(string $email, string $title = '', $attributes = ''): string { + $count = 0; if (trim($title) === '') { $title = $email; } diff --git a/system/Images/Handlers/ImageMagickHandler.php b/system/Images/Handlers/ImageMagickHandler.php index b96fdc06d20d..41274c6a9591 100644 --- a/system/Images/Handlers/ImageMagickHandler.php +++ b/system/Images/Handlers/ImageMagickHandler.php @@ -322,7 +322,10 @@ protected function supportedFormatCheck() */ protected function _text(string $text, array $options = []) { - $cmd = ''; + $xAxis = 0; + $yAxis = 0; + $gravity = ''; + $cmd = ''; // Reverse the vertical offset // When the image is positioned at the bottom diff --git a/system/Model.php b/system/Model.php index 0278be4e4d21..de646c6f8c7c 100644 --- a/system/Model.php +++ b/system/Model.php @@ -427,6 +427,7 @@ protected function doUpdateBatch(?array $set = null, ?string $index = null, int */ protected function doDelete($id = null, bool $purge = false) { + $set = []; $builder = $this->builder(); if ($id) { diff --git a/system/Validation/Rules.php b/system/Validation/Rules.php index 40a5955b157d..93b86ea6b1dd 100644 --- a/system/Validation/Rules.php +++ b/system/Validation/Rules.php @@ -86,7 +86,11 @@ public function greater_than_equal_to(?string $str, string $min): bool public function is_not_unique(?string $str, string $field, array $data): bool { // Grab any data for exclusion of a single row. - [$field, $whereField, $whereValue] = array_pad(explode(',', $field), 3, null); + [$field, $whereField, $whereValue] = array_pad( + explode(',', $field), + 3, + null + ); // Break the table and field apart sscanf($field, '%[^.].%[^.]', $table, $field); @@ -97,7 +101,10 @@ public function is_not_unique(?string $str, string $field, array $data): bool ->where($field, $str) ->limit(1); - if (! empty($whereField) && ! empty($whereValue) && ! preg_match('/^\{(\w+)\}$/', $whereValue)) { + if ( + ! empty($whereField) && ! empty($whereValue) + && ! preg_match('/^\{(\w+)\}$/', $whereValue) + ) { $row = $row->where($whereField, $whereValue); } @@ -125,7 +132,11 @@ public function in_list(?string $value, string $list): bool */ public function is_unique(?string $str, string $field, array $data): bool { - [$field, $ignoreField, $ignoreValue] = array_pad(explode(',', $field), 3, null); + [$field, $ignoreField, $ignoreValue] = array_pad( + explode(',', $field), + 3, + null + ); sscanf($field, '%[^.].%[^.]', $table, $field); @@ -135,7 +146,10 @@ public function is_unique(?string $str, string $field, array $data): bool ->where($field, $str) ->limit(1); - if (! empty($ignoreField) && ! empty($ignoreValue) && ! preg_match('/^\{(\w+)\}$/', $ignoreValue)) { + if ( + ! empty($ignoreField) && ! empty($ignoreValue) + && ! preg_match('/^\{(\w+)\}$/', $ignoreValue) + ) { $row = $row->where("{$ignoreField} !=", $ignoreValue); } diff --git a/system/Validation/StrictRules/Rules.php b/system/Validation/StrictRules/Rules.php index 47dbee9b5ae7..f95bbe7d4083 100644 --- a/system/Validation/StrictRules/Rules.php +++ b/system/Validation/StrictRules/Rules.php @@ -75,7 +75,7 @@ public function exact_length($str, string $val): bool */ public function greater_than($str, string $min): bool { - if (is_int($str)) { + if (is_int($str) || is_float($str)) { $str = (string) $str; } @@ -93,7 +93,7 @@ public function greater_than($str, string $min): bool */ public function greater_than_equal_to($str, string $min): bool { - if (is_int($str)) { + if (is_int($str) || is_float($str)) { $str = (string) $str; } @@ -117,7 +117,34 @@ public function greater_than_equal_to($str, string $min): bool */ public function is_not_unique($str, string $field, array $data): bool { - return $this->nonStrictRules->is_not_unique($str, $field, $data); + if (is_object($str) || is_array($str)) { + return false; + } + + // Grab any data for exclusion of a single row. + [$field, $whereField, $whereValue] = array_pad( + explode(',', $field), + 3, + null + ); + + // Break the table and field apart + sscanf($field, '%[^.].%[^.]', $table, $field); + + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) + ->select('1') + ->where($field, $str) + ->limit(1); + + if ( + ! empty($whereField) && ! empty($whereValue) + && ! preg_match('/^\{(\w+)\}$/', $whereValue) + ) { + $row = $row->where($whereField, $whereValue); + } + + return $row->get()->getRow() !== null; } /** @@ -151,7 +178,32 @@ public function in_list($value, string $list): bool */ public function is_unique($str, string $field, array $data): bool { - return $this->nonStrictRules->is_unique($str, $field, $data); + if (is_object($str) || is_array($str)) { + return false; + } + + [$field, $ignoreField, $ignoreValue] = array_pad( + explode(',', $field), + 3, + null + ); + + sscanf($field, '%[^.].%[^.]', $table, $field); + + $row = Database::connect($data['DBGroup'] ?? null) + ->table($table) + ->select('1') + ->where($field, $str) + ->limit(1); + + if ( + ! empty($ignoreField) && ! empty($ignoreValue) + && ! preg_match('/^\{(\w+)\}$/', $ignoreValue) + ) { + $row = $row->where("{$ignoreField} !=", $ignoreValue); + } + + return $row->get()->getRow() === null; } /** @@ -161,7 +213,7 @@ public function is_unique($str, string $field, array $data): bool */ public function less_than($str, string $max): bool { - if (is_int($str)) { + if (is_int($str) || is_float($str)) { $str = (string) $str; } @@ -179,7 +231,7 @@ public function less_than($str, string $max): bool */ public function less_than_equal_to($str, string $max): bool { - if (is_int($str)) { + if (is_int($str) || is_float($str)) { $str = (string) $str; } diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index 2e8c3be0d625..a0b5280ec6bc 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -266,6 +266,8 @@ public function testRouteTo() { // prime the pump $routes = service('routes'); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $this->assertSame('/path/string/to/13', route_to('myController::goto', 'string', 13)); @@ -275,6 +277,8 @@ public function testRouteToInCliWithoutLocaleInRoute() { Services::createRequest(new App(), true); $routes = service('routes'); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $this->assertSame('/path/string/to/13', route_to('myController::goto', 'string', 13)); @@ -284,6 +288,8 @@ public function testRouteToInCliWithLocaleInRoute() { Services::createRequest(new App(), true); $routes = service('routes'); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('{locale}/path/(:any)/to/(:num)', 'myController::goto/$1/$2', ['as' => 'path-to']); $this->assertSame( @@ -296,6 +302,8 @@ public function testRouteToWithUnsupportedLocale() { Services::createRequest(new App(), false); $routes = service('routes'); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('{locale}/path/(:any)/to/(:num)', 'myController::goto/$1/$2', ['as' => 'path-to']); $this->assertSame( diff --git a/tests/system/Database/Builder/SelectTest.php b/tests/system/Database/Builder/SelectTest.php index 60919a87dd8d..af7bf96d119e 100644 --- a/tests/system/Database/Builder/SelectTest.php +++ b/tests/system/Database/Builder/SelectTest.php @@ -309,4 +309,18 @@ public function testSelectSubquery() $this->assertSame($expected, str_replace("\n", ' ', $builder->getCompiledSelect())); } + + public function testSelectResetQuery() + { + $builder = new BaseBuilder('users', $this->db); + $builder->select('name, role'); + + $builder->resetQuery(); + + $sql = $builder->getCompiledSelect(); + $this->assertSame( + 'SELECT * FROM "users"', + str_replace("\n", ' ', $sql) + ); + } } diff --git a/tests/system/Database/Live/MetadataTest.php b/tests/system/Database/Live/MetadataTest.php index d698f647abe5..1506c7b3d2f5 100644 --- a/tests/system/Database/Live/MetadataTest.php +++ b/tests/system/Database/Live/MetadataTest.php @@ -123,6 +123,8 @@ public function testListTablesConstrainedByPrefixReturnsOnlyTablesWithMatchingPr public function testListTablesConstrainedByExtraneousPrefixReturnsOnlyTheExtraneousTable() { + $oldPrefix = ''; + try { $this->createExtraneousTable(); diff --git a/tests/system/Helpers/URLHelper/MiscUrlTest.php b/tests/system/Helpers/URLHelper/MiscUrlTest.php index 8181705389ca..fb949f2e9ecc 100644 --- a/tests/system/Helpers/URLHelper/MiscUrlTest.php +++ b/tests/system/Helpers/URLHelper/MiscUrlTest.php @@ -835,6 +835,8 @@ public function testUrlTo(string $expected, string $input, ...$args) $_SERVER['HTTP_HOST'] = 'example.com'; $routes = service('routes'); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2', ['as' => 'gotoPage']); $routes->add('route/(:any)/to/(:num)', 'myOtherController::goto/$1/$2'); diff --git a/tests/system/Router/RouteCollectionReverseRouteTest.php b/tests/system/Router/RouteCollectionReverseRouteTest.php index 8f5bea1996bf..2e6de5aacdf7 100644 --- a/tests/system/Router/RouteCollectionReverseRouteTest.php +++ b/tests/system/Router/RouteCollectionReverseRouteTest.php @@ -56,6 +56,8 @@ public function testReverseRoutingFindsSimpleMatch() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $match = $routes->reverseRoute('myController::goto', 'string', 13); @@ -67,6 +69,8 @@ public function testReverseRoutingWithLocaleAndFindsSimpleMatch() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('{locale}/path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $match = $routes->reverseRoute('myController::goto', 'string', 13); @@ -78,6 +82,8 @@ public function testReverseRoutingReturnsFalseWithBadParamCount() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1'); $this->assertFalse($routes->reverseRoute('myController::goto', 'string', 13)); @@ -87,6 +93,8 @@ public function testReverseRoutingReturnsFalseWithNoMatch() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $this->assertFalse($routes->reverseRoute('myBadController::goto', 'string', 13)); @@ -96,6 +104,8 @@ public function testReverseRoutingThrowsExceptionWithBadParamTypes() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $this->expectException(RouterException::class); diff --git a/tests/system/Router/RouteCollectionTest.php b/tests/system/Router/RouteCollectionTest.php index fbd99fd88b62..70d378467414 100644 --- a/tests/system/Router/RouteCollectionTest.php +++ b/tests/system/Router/RouteCollectionTest.php @@ -889,6 +889,8 @@ public function testNamedRoutesFillInParams() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2', ['as' => 'namedRoute']); $match = $routes->reverseRoute('namedRoute', 'string', 13); @@ -900,6 +902,8 @@ public function testNamedRoutesWithLocaleAndFillInParams() { $routes = $this->getCollector(); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('{locale}/path/(:any)/to/(:num)', 'myController::goto/$1/$2', ['as' => 'namedRoute']); $match = $routes->reverseRoute('namedRoute', 'string', 13); diff --git a/tests/system/Validation/DatabaseRelatedRulesTest.php b/tests/system/Validation/DatabaseRelatedRulesTest.php index 42881bab444e..e9abd11f83aa 100644 --- a/tests/system/Validation/DatabaseRelatedRulesTest.php +++ b/tests/system/Validation/DatabaseRelatedRulesTest.php @@ -11,10 +11,7 @@ namespace CodeIgniter\Validation; -use CodeIgniter\Test\CIUnitTestCase; -use CodeIgniter\Test\DatabaseTestTrait; -use Config\Database; -use Config\Services; +use CodeIgniter\Validation\StrictRules\DatabaseRelatedRulesTest as StrictDatabaseRelatedRulesTest; use Tests\Support\Validation\TestRules; /** @@ -22,12 +19,9 @@ * * @group DatabaseLive */ -final class DatabaseRelatedRulesTest extends CIUnitTestCase +final class DatabaseRelatedRulesTest extends StrictDatabaseRelatedRulesTest { - use DatabaseTestTrait; - - private Validation $validation; - private array $config = [ + protected array $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -45,173 +39,8 @@ final class DatabaseRelatedRulesTest extends CIUnitTestCase ], ]; - protected function setUp(): void - { - parent::setUp(); - $this->validation = new Validation((object) $this->config, Services::renderer()); - $this->validation->reset(); - } - - public function testIsUniqueFalse(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = ['email' => 'derek@world.com']; - $this->validation->setRules(['email' => 'is_unique[user.email]']); - $this->assertFalse($this->validation->run($data)); - } - - public function testIsUniqueTrue(): void - { - $data = ['email' => 'derek@world.co.uk']; - $this->validation->setRules(['email' => 'is_unique[user.email]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsUniqueIgnoresParams(): void - { - $db = Database::connect(); - $db - ->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = ['email' => 'derek@world.co.uk']; - $this->validation->setRules(['email' => "is_unique[user.email,id,{$row->id}]"]); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsUniqueIgnoresParamsPlaceholders(): void - { - $this->hasInDatabase('user', [ - 'name' => 'Derek', - 'email' => 'derek@world.co.uk', - 'country' => 'GB', - ]); - - $row = Database::connect() - ->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'id' => $row->id, - 'email' => 'derek@world.co.uk', - ]; - - $this->validation->setRules(['email' => 'is_unique[user.email,id,{id}]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsUniqueByManualRun(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', [])); - } - - public function testIsNotUniqueFalse(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = ['email' => 'derek1@world.com']; - $this->validation->setRules(['email' => 'is_not_unique[user.email]']); - $this->assertFalse($this->validation->run($data)); - } - - public function testIsNotUniqueTrue(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Derek Travis', - 'email' => 'derek@world.com', - 'country' => 'Elbonia', - ]); - - $data = ['email' => 'derek@world.com']; - $this->validation->setRules(['email' => 'is_not_unique[user.email]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsNotUniqueIgnoresParams(): void + protected function createRules() { - $db = Database::connect(); - $db->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $row = $db->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = ['email' => 'derek@world.co.uk']; - $this->validation->setRules(['email' => "is_not_unique[user.email,id,{$row->id}]"]); - $this->assertFalse($this->validation->run($data)); - } - - public function testIsNotUniqueIgnoresParamsPlaceholders(): void - { - $this->hasInDatabase('user', [ - 'name' => 'Derek', - 'email' => 'derek@world.co.uk', - 'country' => 'GB', - ]); - - $row = Database::connect() - ->table('user') - ->limit(1) - ->get() - ->getRow(); - - $data = [ - 'id' => $row->id, - 'email' => 'derek@world.co.uk', - ]; - $this->validation->setRules(['email' => 'is_not_unique[user.email,id,{id}]']); - $this->assertTrue($this->validation->run($data)); - } - - public function testIsNotUniqueByManualRun(): void - { - Database::connect() - ->table('user') - ->insert([ - 'name' => 'Developer A', - 'email' => 'deva@example.com', - 'country' => 'Elbonia', - ]); - - $this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); + return new Rules(); } } diff --git a/tests/system/Validation/RulesTest.php b/tests/system/Validation/RulesTest.php index 19e6bde1f18c..3bf60aca8131 100644 --- a/tests/system/Validation/RulesTest.php +++ b/tests/system/Validation/RulesTest.php @@ -427,6 +427,9 @@ public function greaterThanProvider(): Generator ['-10', '-11', true], ['10', '9', true], ['10', '10', false], + ['10.1', '10', true], + ['10.0', '10', false], + ['9.9', '10', false], ['10', 'a', false], ['10a', '10', false], [null, null, false], @@ -449,6 +452,9 @@ public function greaterThanEqualProvider(): Generator ['0', '0', true], ['1', '0', true], ['-1', '0', false], + ['1.0', '1', true], + ['1.1', '1', true], + ['0.9', '1', false], ['10a', '0', false], [null, null, false], ['1', null, true], @@ -473,6 +479,9 @@ public function lessThanProvider(): Generator ['9', '10', true], ['10', '9', false], ['10', '10', false], + ['9.9', '10', true], + ['10.1', '10', false], + ['10.0', '10', false], ['10', 'a', true], ['10a', '10', false], [null, null, false], @@ -482,7 +491,7 @@ public function lessThanProvider(): Generator /** * @dataProvider lessThanEqualProvider */ - public function testLessEqualThan(?string $first, ?string $second, bool $expected): void + public function testLessThanEqual(?string $first, ?string $second, bool $expected): void { $data = ['foo' => $first]; $this->validation->setRules(['foo' => "less_than_equal_to[{$second}]"]); @@ -495,6 +504,9 @@ public function lessThanEqualProvider(): Generator ['0', '0', true], ['1', '0', false], ['-1', '0', true], + ['1.0', '1', true], + ['0.9', '1', true], + ['1.1', '1', false], ['10a', '0', false], [null, null, false], ['1', null, false], diff --git a/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php b/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php index 79c9c7d39e9f..9b56dc3e3205 100644 --- a/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php +++ b/tests/system/Validation/StrictRules/DatabaseRelatedRulesTest.php @@ -21,14 +21,16 @@ /** * @internal * + * @no-final + * * @group DatabaseLive */ -final class DatabaseRelatedRulesTest extends CIUnitTestCase +class DatabaseRelatedRulesTest extends CIUnitTestCase { use DatabaseTestTrait; - private Validation $validation; - private array $config = [ + protected Validation $validation; + protected array $config = [ 'ruleSets' => [ Rules::class, FormatRules::class, @@ -53,6 +55,11 @@ protected function setUp(): void $this->validation->reset(); } + protected function createRules() + { + return new Rules(); + } + public function testIsUniqueFalse(): void { Database::connect() @@ -128,7 +135,22 @@ public function testIsUniqueByManualRun(): void 'country' => 'Elbonia', ]); - $this->assertFalse((new Rules())->is_unique('deva@example.com', 'user.email,id,{id}', [])); + $this->assertFalse($this->createRules()->is_unique('deva@example.com', 'user.email,id,{id}', [])); + } + + public function testIsUniqueIntValueByManualRun(): void + { + Database::connect() + ->table('user') + ->insert([ + 'name' => 'Developer A', + 'email' => 'deva@example.com', + 'country' => 'Elbonia', + ]); + + $result = $this->createRules()->is_unique(1, 'user.id', []); + + $this->assertFalse($result); } public function testIsNotUniqueFalse(): void @@ -213,6 +235,6 @@ public function testIsNotUniqueByManualRun(): void 'country' => 'Elbonia', ]); - $this->assertTrue((new Rules())->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); + $this->assertTrue($this->createRules()->is_not_unique('deva@example.com', 'user.email,id,{id}', [])); } } diff --git a/tests/system/Validation/StrictRules/RulesTest.php b/tests/system/Validation/StrictRules/RulesTest.php index d153367b8220..4c0e84274226 100644 --- a/tests/system/Validation/StrictRules/RulesTest.php +++ b/tests/system/Validation/StrictRules/RulesTest.php @@ -106,6 +106,9 @@ public function provideGreaterThanEqualStrict(): Generator [0, '0', true], [1, '0', true], [-1, '0', false], + [1.0, '1', true], + [1.1, '1', true], + [0.9, '1', false], [true, '0', false], ]; } @@ -129,6 +132,9 @@ public function provideGreaterThanStrict(): Generator [-10, '-11', true], [10, '9', true], [10, '10', false], + [10.1, '10', true], + [10.0, '10', false], + [9.9, '10', false], [10, 'a', false], [true, '0', false], ]; @@ -154,6 +160,9 @@ public function provideLessThanStrict(): Generator [9, '10', true], [10, '9', false], [10, '10', false], + [9.9, '10', true], + [10.1, '10', false], + [10.0, '10', false], [10, 'a', true], [true, '0', false], ]; @@ -178,6 +187,9 @@ public function provideLessThanEqualStrict(): Generator [0, '0', true], [1, '0', false], [-1, '0', true], + [1.0, '1', true], + [0.9, '1', true], + [1.1, '1', false], [true, '0', false], ]; } diff --git a/tests/system/Validation/ValidationTest.php b/tests/system/Validation/ValidationTest.php index 100cf1535495..6597866b3f88 100644 --- a/tests/system/Validation/ValidationTest.php +++ b/tests/system/Validation/ValidationTest.php @@ -288,6 +288,7 @@ public function testClosureRuleWithLabel(): void */ public function testCanValidatetArrayData($value, bool $expected): void { + $data = []; $this->validation->setRules(['arr' => 'is_array']); $data['arr'] = $value; diff --git a/tests/system/View/ParserPluginTest.php b/tests/system/View/ParserPluginTest.php index 3c8c781d0edc..daea90de7fa7 100644 --- a/tests/system/View/ParserPluginTest.php +++ b/tests/system/View/ParserPluginTest.php @@ -96,6 +96,8 @@ public function testRoute() { // prime the pump $routes = service('routes'); + // @TODO Do not put any placeholder after (:any). + // Because the number of parameters passed to the controller method may change. $routes->add('path/(:any)/to/(:num)', 'myController::goto/$1/$2'); $template = '{+ route myController::goto string 13 +}'; diff --git a/user_guide_src/source/changelogs/index.rst b/user_guide_src/source/changelogs/index.rst index 29f118e55f86..401d178f285f 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.3.1 v4.3.0 v4.2.12 v4.2.11 diff --git a/user_guide_src/source/changelogs/v4.2.3.rst b/user_guide_src/source/changelogs/v4.2.3.rst index cfa036fd69b8..69a2889a810e 100644 --- a/user_guide_src/source/changelogs/v4.2.3.rst +++ b/user_guide_src/source/changelogs/v4.2.3.rst @@ -9,26 +9,11 @@ Release Date: August 6, 2022 :local: :depth: 2 -BREAKING -******** - -none. - Enhancements ************ - Now ``Security::generateHash()`` is public, and can be used to regenerate CSRF token manually when ``Config\Security::$regenerate`` is false. -Changes -******* - -none. - -Deprecations -************ - -none. - Bugs Fixed ********** diff --git a/user_guide_src/source/changelogs/v4.2.5.rst b/user_guide_src/source/changelogs/v4.2.5.rst index c9ff36b05508..96908b750843 100644 --- a/user_guide_src/source/changelogs/v4.2.5.rst +++ b/user_guide_src/source/changelogs/v4.2.5.rst @@ -21,16 +21,6 @@ Enhancements - Kint has been updated to 4.2.0. -Changes -******* - -none. - -Deprecations -************ - -none. - Bugs Fixed ********** - When using subqueries in the main query, prefixes are added to the table alias. diff --git a/user_guide_src/source/changelogs/v4.2.6.rst b/user_guide_src/source/changelogs/v4.2.6.rst index 0b86636e0dcb..154927470ba7 100644 --- a/user_guide_src/source/changelogs/v4.2.6.rst +++ b/user_guide_src/source/changelogs/v4.2.6.rst @@ -9,21 +9,6 @@ Release Date: September 4, 2022 :local: :depth: 2 -BREAKING -******** - -none. - -Enhancements -************ - -none. - -Changes -******* - -none. - Deprecations ************ diff --git a/user_guide_src/source/changelogs/v4.2.7.rst b/user_guide_src/source/changelogs/v4.2.7.rst index c7d29b0ce70e..920ba72761ce 100644 --- a/user_guide_src/source/changelogs/v4.2.7.rst +++ b/user_guide_src/source/changelogs/v4.2.7.rst @@ -22,27 +22,12 @@ BREAKING - ``Time::__toString()`` is now locale-independent. It returns database-compatible strings like '2022-09-07 12:00:00' in any locale. - The Validation rule ``Validation\Rule::required_without()`` and ``Validation\StrictRules\Rule::required_without()`` parameters have been changed and the logic of these rule has also been fixed. -Enhancements -************ - -none. - Message Changes *************** - Fixed typos in some items in ``Language/en/Email.php``. - Added missing item ``valid_json`` in ``Language/en/Validation.php``. -Changes -******* - -none. - -Deprecations -************ - -none. - Bugs Fixed ********** diff --git a/user_guide_src/source/changelogs/v4.2.8.rst b/user_guide_src/source/changelogs/v4.2.8.rst index 0463b4883def..4b6d83c98a6a 100644 --- a/user_guide_src/source/changelogs/v4.2.8.rst +++ b/user_guide_src/source/changelogs/v4.2.8.rst @@ -9,26 +9,6 @@ Release Date: October 30, 2022 :local: :depth: 2 -BREAKING -******** - -none. - -Enhancements -************ - -none. - -Message Changes -*************** - -none. - -Changes -******* - -none. - Deprecations ************ diff --git a/user_guide_src/source/changelogs/v4.3.0.rst b/user_guide_src/source/changelogs/v4.3.0.rst index 671ce5c6cf0f..ed6047cd320e 100644 --- a/user_guide_src/source/changelogs/v4.3.0.rst +++ b/user_guide_src/source/changelogs/v4.3.0.rst @@ -369,3 +369,7 @@ Bugs Fixed - Fixed a bug with variable filtering in JSON requests using with ``IncomingRequest::getVar()`` or ``IncomingRequest::getJsonVar()`` methods. - Fixed a bug when variable type may be changed when using a specified index with ``IncomingRequest::getVar()`` or ``IncomingRequest::getJsonVar()`` methods. - Fixed a bug that Honeypot field appears when CSP is enabled. See also :ref:`upgrade-430-honeypot-and-csp`. + +See the repo's +`CHANGELOG.md `_ +for a complete list of bugs fixed. diff --git a/user_guide_src/source/changelogs/v4.3.1.rst b/user_guide_src/source/changelogs/v4.3.1.rst new file mode 100644 index 000000000000..f671fa3ffcc0 --- /dev/null +++ b/user_guide_src/source/changelogs/v4.3.1.rst @@ -0,0 +1,23 @@ +Version 4.3.1 +############# + +Release Date: January 14, 2023 + +**4.3.1 release of CodeIgniter4** + +.. contents:: + :local: + :depth: 3 + +Bugs Fixed +********** + +* Fixed: some environment variable (**.env**) values were not reflected in Email Config +* Fixed: TypeError in Validation ``is_unique`` and ``is_not_unique`` +* Fixed: revert method name ``BaseBuilder::resetQuery()`` changed accidentally +* Fixed: handling float in Validation Strcit Rules (``greater_than``, ``greater_than_equal_to``, ``less_than``, ``less_than_equal_to``) +* Fixed: missing instruction for ``Config\Exceptions`` in PHP 8.2 in the user guide + +See the repo's +`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 16e0209a916d..a0484b3d0c3c 100644 --- a/user_guide_src/source/conf.py +++ b/user_guide_src/source/conf.py @@ -26,7 +26,7 @@ version = '4.3' # The full version, including alpha/beta/rc tags. -release = '4.3.0' +release = '4.3.1' # -- General configuration --------------------------------------------------- diff --git a/user_guide_src/source/helpers/cookie_helper.rst b/user_guide_src/source/helpers/cookie_helper.rst index d19f4dbe5589..a26bf180f27b 100755 --- a/user_guide_src/source/helpers/cookie_helper.rst +++ b/user_guide_src/source/helpers/cookie_helper.rst @@ -25,7 +25,7 @@ The following functions are available: :param mixed $name: Cookie name *or* associative array of all of the parameters available to this function :param string $value: Cookie value - :param int $expire: Number of seconds until expiration + :param int $expire: Number of seconds until expiration. If set to ``0`` the cookie will only last as long as the browser is open :param string $domain: Cookie domain (usually: .yourdomain.com) :param string $path: Cookie path :param string $prefix: Cookie name prefix. If ``''``, the default from **app/Config/Cookie.php** is used diff --git a/user_guide_src/source/installation/installing_composer.rst b/user_guide_src/source/installation/installing_composer.rst index fc3fbe5c5c7b..97c39b34a19b 100644 --- a/user_guide_src/source/installation/installing_composer.rst +++ b/user_guide_src/source/installation/installing_composer.rst @@ -7,6 +7,8 @@ Composer Installation Composer can be used in several ways to install CodeIgniter4 on your system. +.. important:: CodeIgniter4 requires Composer 2.0.14 or later. + The first technique describes creating a skeleton project using CodeIgniter4, that you would then use as the base for a new webapp. The second technique described below lets you add CodeIgniter4 to an existing diff --git a/user_guide_src/source/installation/upgrade_430.rst b/user_guide_src/source/installation/upgrade_430.rst index 69a4e756b2e0..fb93b74c782b 100644 --- a/user_guide_src/source/installation/upgrade_430.rst +++ b/user_guide_src/source/installation/upgrade_430.rst @@ -1,6 +1,6 @@ -############################# -Upgrading from 4.2.9 to 4.3.0 -############################# +############################## +Upgrading from 4.2.12 to 4.3.0 +############################## Please refer to the upgrade instructions corresponding to your installation method. @@ -12,6 +12,21 @@ Please refer to the upgrade instructions corresponding to your installation meth :local: :depth: 2 +Composer Version +**************** + +.. important:: If you use Composer, CodeIgniter v4.3.0 requires + Composer 2.0.14 or later. + +If you are using older version of Composer, upgrade your ``composer`` tool, +and delete the **vendor/** directory, and run ``composer update`` again. + +The procedure, for example, is as follows:: + + > composer self-update + > rm -rf vendor/ + > composer update + Mandatory File Changes ********************** @@ -33,7 +48,23 @@ The following files received significant changes and Config Files ============ -- **app/Config/Kint.php** has been updated for Kint 5.0. You need to replace ``Kint\Renderer\Renderer`` with ``Kint\Renderer\AbstractRenderer`` and replace ``Renderer::SORT_FULL`` with ``AbstractRenderer::SORT_FULL``. +app/Config/Kint.php +------------------- + +- **app/Config/Kint.php** has been updated for Kint 5.0. +- You need to replace: + + - ``Kint\Renderer\Renderer`` with ``Kint\Renderer\AbstractRenderer`` + - ``Renderer::SORT_FULL`` with ``AbstractRenderer::SORT_FULL`` + +app/Config/Exceptions.php +------------------------- + +- If you are using PHP 8.2, you need to add new properties ``$logDeprecations`` and ``$deprecationLogLevel``. + +Mock Config Classes +------------------- + - If you are using the following Mock Config classes in testing, you need to update the corresponding Config files in **app/Config**: - ``MockAppConfig`` (``Config\App``) @@ -141,12 +172,13 @@ The way error and output streams are captured has changed. Now instead of:: protected function setUp(): void { CITestStreamFilter::$buffer = ''; - $this->stream_filter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + $this->streamFilter = stream_filter_append(STDOUT, 'CITestStreamFilter'); + $this->streamFilter = stream_filter_append(STDERR, 'CITestStreamFilter'); } protected function tearDown(): void { - stream_filter_remove($this->stream_filter); + stream_filter_remove($this->streamFilter); } need to use:: @@ -157,11 +189,13 @@ need to use:: { CITestStreamFilter::registration(); CITestStreamFilter::addOutputFilter(); + CITestStreamFilter::addErrorFilter(); } protected function tearDown(): void { CITestStreamFilter::removeOutputFilter(); + CITestStreamFilter::removeErrorFilter(); } Or use the trait ``CodeIgniter\Test\StreamFilterTrait``. See :ref:`testing-cli-output`. diff --git a/user_guide_src/source/installation/upgrade_431.rst b/user_guide_src/source/installation/upgrade_431.rst new file mode 100644 index 000000000000..4adce6d4af2d --- /dev/null +++ b/user_guide_src/source/installation/upgrade_431.rst @@ -0,0 +1,81 @@ +############################## +Upgrading from 4.3.0 to 4.3.1 +############################## + +Please refer to the upgrade instructions corresponding to your installation method. + +- :ref:`Composer Installation App Starter Upgrading ` +- :ref:`Composer Installation Adding CodeIgniter4 to an Existing Project Upgrading ` +- :ref:`Manual Installation Upgrading ` + +.. contents:: + :local: + :depth: 2 + +Composer Version +**************** + +.. important:: If you use Composer, CodeIgniter v4.3 requires + Composer 2.0.14 or later. + +If you are using older version of Composer, upgrade your ``composer`` tool, +and delete the **vendor/** directory, and run ``composer update`` again. + +The procedure, for example, is as follows:: + + > composer self-update + > rm -rf vendor/ + > composer update + +Mandatory File Changes +********************** + +Config Files +============ + +app/Config/Email.php +-------------------- + +- If you updated **app/Config/Email.php** when upgrading to v4.3.0, you must + set the default values to ``$fromEmail``, ``$fromName``, ``$recipients``, + ``$SMTPHost``, ``$SMTPUser`` and ``$SMTPPass`` to apply environment variable + (**.env**) values. +- If no default values are set, setting environment variables for them will not + be reflected in the Config object. + +app/Config/Exceptions.php +------------------------- + +- If you are using PHP 8.2, you need to add new properties ``$logDeprecations`` and ``$deprecationLogLevel``. + +Project Files +************* + +Some files in the **project space** (root, app, public, writable) received updates. Due to +these files being outside of the **system** scope they will not be changed without your intervention. + +There are some third-party CodeIgniter modules available to assist with merging changes to +the project space: `Explore on Packagist `_. + +Content Changes +=============== + +The following files received significant changes (including deprecations or visual adjustments) +and it is recommended that you merge the updated versions with your application: + +Config +------ + +- app/Config/Encryption.php + - Set the default value ``''`` to ``$fromEmail``, ``$fromName``, + ``$recipients``, ``$SMTPHost``, ``$SMTPUser`` and ``$SMTPPass`` + to apply environment variable (**.env**) values. + +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: + +- app/Config/Email.php +- composer.json diff --git a/user_guide_src/source/installation/upgrading.rst b/user_guide_src/source/installation/upgrading.rst index 1608661204d7..f5600aa52d00 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_431 upgrade_430 upgrade_4212 upgrade_4211 diff --git a/user_guide_src/source/libraries/sessions.rst b/user_guide_src/source/libraries/sessions.rst index 866236d7fde2..d7b68b36895f 100644 --- a/user_guide_src/source/libraries/sessions.rst +++ b/user_guide_src/source/libraries/sessions.rst @@ -525,6 +525,14 @@ into using `tmpfs php spark make:migration --session > php spark migrate -This command will take the **savePath** and **matchIP** settings into account +This command will take the ``$savePath`` and ``$matchIP`` settings into account when it generates the code. -.. important:: Only MySQL and PostgreSQL databases are officially - supported, due to lack of advisory locking mechanisms on other - platforms. Using sessions without locks can cause all sorts of - problems, especially with heavy usage of AJAX, and we will not - support such cases. Use ``session_write_close()`` after you've - done processing session data if you're having performance - issues. - .. _sessions-redishandler-driver: RedisHandler Driver @@ -623,6 +626,9 @@ bundled with PHP. Chances are, you're only be using the RedisHandler driver only if you're already both familiar with Redis and using it for other purposes. +Configure RedisHandler +---------------------- + Just as with the 'FileHandler' and 'DatabaseHandler' drivers, you must also configure the storage location for your sessions via the ``$savePath`` setting. @@ -632,7 +638,7 @@ link you to it: https://github.com/phpredis/phpredis -.. warning:: CodeIgniter's Session library does NOT use the actual 'redis' +.. important:::: CodeIgniter's Session library does NOT use the actual 'redis' ``session.save_handler``. Take note **only** of the path format in the link above. @@ -665,6 +671,9 @@ deleted after Y seconds have passed (but not necessarily that it won't expire earlier than that time). This happens very rarely, but should be considered as it may result in loss of sessions. +Configure RedisHandler +---------------------- + The ``$savePath`` format is fairly straightforward here, being just a ``host:port`` pair: diff --git a/user_guide_src/source/libraries/sessions/039.php b/user_guide_src/source/libraries/sessions/039.php index 77a0a02b0222..a561e4a49cb6 100644 --- a/user_guide_src/source/libraries/sessions/039.php +++ b/user_guide_src/source/libraries/sessions/039.php @@ -9,7 +9,9 @@ class Session extends BaseConfig { // ... public string $driver = 'CodeIgniter\Session\Handlers\DatabaseHandler'; + // ... public string $savePath = 'ci_sessions'; + // ... } diff --git a/user_guide_src/source/libraries/sessions/041.php b/user_guide_src/source/libraries/sessions/041.php index 4f26bf79661b..091ec22ce651 100644 --- a/user_guide_src/source/libraries/sessions/041.php +++ b/user_guide_src/source/libraries/sessions/041.php @@ -9,7 +9,9 @@ class Session extends BaseConfig { // ... public string $driver = 'CodeIgniter\Session\Handlers\RedisHandler'; + // ... public string $savePath = 'tcp://localhost:6379'; + // ... } diff --git a/user_guide_src/source/libraries/sessions/042.php b/user_guide_src/source/libraries/sessions/042.php index 3cdbe41f2ae1..92ba42b9af3d 100644 --- a/user_guide_src/source/libraries/sessions/042.php +++ b/user_guide_src/source/libraries/sessions/042.php @@ -9,7 +9,9 @@ class Session extends BaseConfig { // ... public string $driver = 'CodeIgniter\Session\Handlers\MemcachedHandler'; + // ... public string $savePath = 'localhost:11211'; + // ... } diff --git a/user_guide_src/source/libraries/validation/030.php b/user_guide_src/source/libraries/validation/030.php index f7c69eb42e99..86e4aaf85583 100644 --- a/user_guide_src/source/libraries/validation/030.php +++ b/user_guide_src/source/libraries/validation/030.php @@ -1,7 +1,9 @@ - + + + diff --git a/user_guide_src/source/models/model/033.php b/user_guide_src/source/models/model/033.php index 32005c35b635..f0e48d26de73 100644 --- a/user_guide_src/source/models/model/033.php +++ b/user_guide_src/source/models/model/033.php @@ -1,7 +1,7 @@
$error): ?> -

+

diff --git a/user_guide_src/source/outgoing/response.rst b/user_guide_src/source/outgoing/response.rst index f3e0909487a4..c3c10bc8d40d 100644 --- a/user_guide_src/source/outgoing/response.rst +++ b/user_guide_src/source/outgoing/response.rst @@ -366,7 +366,7 @@ The methods provided by the parent class that are available are: :param array|Cookie|string $name: Cookie name or an array of parameters or an instance of ``CodeIgniter\Cookie\Cookie`` :param string $value: Cookie value - :param int $expire: Cookie expiration time in seconds + :param int $expire: Cookie expiration time in seconds. If set to ``0`` the cookie will only last as long as the browser is open :param string $domain: Cookie domain :param string $path: Cookie path :param string $prefix: Cookie name prefix. If set to ``''``, the default value from **app/Config/Cookie.php** will be used