From 357b0afc18d0d3e43e9de74439e6be5427e155e1 Mon Sep 17 00:00:00 2001 From: Bogdan Date: Thu, 9 Jul 2026 23:42:08 +0200 Subject: [PATCH] fix: toRawArray() converts DateTime objects to strings This squashes several fixes regarding Entity::toRawArray returning string values instead of Time objects, addressing issue #8302. It also updates DatetimeCast to handle string values to prevent DataConverter crashes, and applies phpstan, rector, and cs-fix formatting. --- rector.php | 2 - system/DataCaster/Cast/DatetimeCast.php | 12 +- system/Entity/Entity.php | 6 +- utils/phpstan-baseline/argument.type.neon | 127 ++++++++++++++++++- utils/phpstan-baseline/empty.notAllowed.neon | 2 +- utils/phpstan-baseline/loader.neon | 2 +- 6 files changed, 141 insertions(+), 10 deletions(-) diff --git a/rector.php b/rector.php index ba14babedae0..a578508ecefe 100644 --- a/rector.php +++ b/rector.php @@ -12,7 +12,6 @@ */ use Rector\Caching\ValueObject\Storage\FileCacheStorage; -use Rector\CodeQuality\Rector\BooleanNot\NegatedAndsToPositiveOrsRector; use Rector\CodeQuality\Rector\Empty_\SimplifyEmptyCheckOnEmptyArrayRector; use Rector\CodeQuality\Rector\FuncCall\CompactToVariablesRector; use Rector\CodeQuality\Rector\FunctionLike\SimplifyUselessVariableRector; @@ -176,7 +175,6 @@ ], // to be applied in separate PRs to ease review - NegatedAndsToPositiveOrsRector::class, ]) // auto import fully qualified class names ->withImportNames() diff --git a/system/DataCaster/Cast/DatetimeCast.php b/system/DataCaster/Cast/DatetimeCast.php index 398fdc7beed7..ed9e9e43b5c2 100644 --- a/system/DataCaster/Cast/DatetimeCast.php +++ b/system/DataCaster/Cast/DatetimeCast.php @@ -16,6 +16,8 @@ use CodeIgniter\Database\BaseConnection; use CodeIgniter\Exceptions\InvalidArgumentException; use CodeIgniter\I18n\Time; +use DateTimeInterface; +use Exception; /** * Class DatetimeCast @@ -51,7 +53,15 @@ public static function set( array $params = [], ?object $helper = null, ): string { - if (! $value instanceof Time) { + if (is_string($value)) { + try { + $value = Time::parse($value); + } catch (Exception) { + self::invalidTypeValueError($value); + } + } + + if (! $value instanceof DateTimeInterface) { self::invalidTypeValueError($value); } diff --git a/system/Entity/Entity.php b/system/Entity/Entity.php index a67c44b6fd1c..c066d2aa69c6 100644 --- a/system/Entity/Entity.php +++ b/system/Entity/Entity.php @@ -261,9 +261,7 @@ public function toRawArray(bool $onlyChanged = false, bool $recursive = false): // When returning everything if (! $onlyChanged) { - return $recursive - ? array_map($convert, $this->attributes) - : $this->attributes; + return array_map($convert, $this->attributes); } // When filtering by changed values only @@ -335,7 +333,7 @@ public function toRawArray(bool $onlyChanged = false, bool $recursive = false): } // non-recursive changed value - $return[$key] = $value; + $return[$key] = $convert($value); } return $return; diff --git a/utils/phpstan-baseline/argument.type.neon b/utils/phpstan-baseline/argument.type.neon index 7fbc636537e7..abc47da9d0b8 100644 --- a/utils/phpstan-baseline/argument.type.neon +++ b/utils/phpstan-baseline/argument.type.neon @@ -1,7 +1,17 @@ -# total 68 errors +# total 228 errors parameters: ignoreErrors: + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\RedirectResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../system/Config/Services.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 2 + path: ../../system/Config/Services.php + - message: '#^Parameter \#3 \.\.\.\$arrays of function array_map expects array, int\|string given\.$#' count: 1 @@ -22,6 +32,26 @@ parameters: count: 1 path: ../../system/Database/SQLite3/Builder.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../system/HTTP/CURLRequest.php + + - + message: '#^Parameter \#1 \$config of method CodeIgniter\\HTTP\\Response\:\:__construct\(\) expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../system/HTTP/DownloadResponse.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\Test\\Mock\\MockResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 2 + path: ../../tests/system/API/ResponseTraitTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 19 + path: ../../tests/system/Cache/ResponseCacheTest.php + - message: '#^Parameter \#2 \$to of method CodeIgniter\\Router\\RouteCollection\:\:add\(\) expects array\|\(Closure\(mixed \.\.\.\)\: \(CodeIgniter\\HTTP\\ResponseInterface\|string\|void\)\)\|string, Closure\(mixed\)\: CodeIgniter\\HTTP\\ResponseInterface given\.$#' count: 1 @@ -42,6 +72,11 @@ parameters: count: 1 path: ../../tests/system/CodeIgniterTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\RedirectResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 3 + path: ../../tests/system/CommonFunctionsTest.php + - message: '#^Parameter \#1 \$expected of method PHPUnit\\Framework\\Assert\:\:assertInstanceOf\(\) expects class\-string\, string given\.$#' count: 1 @@ -52,6 +87,16 @@ parameters: count: 2 path: ../../tests/system/Config/FactoriesTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\Test\\Mock\\MockResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 7 + path: ../../tests/system/Config/ServicesTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/ControllerTest.php + - message: '#^Parameter \#1 \$from of method CodeIgniter\\Database\\BaseBuilder\:\:from\(\) expects array\|string, null given\.$#' count: 1 @@ -97,16 +142,66 @@ parameters: count: 1 path: ../../tests/system/Debug/TimerTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\RedirectResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/Filters/PageCacheTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 10 + path: ../../tests/system/Filters/PageCacheTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/HTTP/CURLRequestShareOptionsTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/HTTP/CURLRequestTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 6 + path: ../../tests/system/HTTP/ContentSecurityPolicyTest.php + - message: '#^Parameter \#1 \$array of method CodeIgniter\\Superglobals\:\:setServerArray\(\) expects array\\|float\|int\|string\>, array\ given\.$#' count: 1 path: ../../tests/system/HTTP/MessageTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\RedirectResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 15 + path: ../../tests/system/HTTP/RedirectResponseTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 27 + path: ../../tests/system/HTTP/ResponseCookieTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 5 + path: ../../tests/system/HTTP/ResponseSendTest.php + - message: '#^Parameter \#3 \$expire of method CodeIgniter\\HTTP\\Response\:\:setCookie\(\) expects int, string given\.$#' count: 1 path: ../../tests/system/HTTP/ResponseSendTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 43 + path: ../../tests/system/HTTP/ResponseTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\Test\\Mock\\MockResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 2 + path: ../../tests/system/HTTP/ResponseTest.php + - message: '#^Parameter \#1 \$data of method CodeIgniter\\HTTP\\Message\:\:setBody\(\) expects string, array\\|string\> given\.$#' count: 2 @@ -122,6 +217,11 @@ parameters: count: 1 path: ../../tests/system/HTTP/SiteURITest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\Test\\Mock\\MockResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/Helpers/CookieHelperTest.php + - message: '#^Parameter \#2 \$value of function form_hidden expects array\|string, null given\.$#' count: 1 @@ -152,11 +252,21 @@ parameters: count: 2 path: ../../tests/system/Images/GDHandlerTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\Test\\Mock\\MockResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/Log/Handlers/ChromeLoggerHandlerTest.php + - message: '#^Parameter \#2 \$message of method CodeIgniter\\Log\\Handlers\\ChromeLoggerHandler\:\:handle\(\) expects string, stdClass given\.$#' count: 1 path: ../../tests/system/Log/Handlers/ChromeLoggerHandlerTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 2 + path: ../../tests/system/RESTful/ResourceControllerTest.php + - message: '#^Parameter \#1 \$format of method CodeIgniter\\RESTful\\ResourceController\:\:setFormat\(\) expects ''json''\|''xml'', ''Nonsense'' given\.$#' count: 1 @@ -172,6 +282,11 @@ parameters: count: 1 path: ../../tests/system/Test/FeatureTestTraitTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 2 + path: ../../tests/system/Test/TestCaseEmissionsTest.php + - message: '#^Parameter \#1 \$body of method CodeIgniter\\HTTP\\Response\:\:setJSON\(\) expects array\|object\|string, false given\.$#' count: 1 @@ -182,6 +297,16 @@ parameters: count: 1 path: ../../tests/system/Test/TestResponseTest.php + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\RedirectResponse constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 5 + path: ../../tests/system/Test/TestResponseTest.php + + - + message: '#^Parameter \#1 \$config of class CodeIgniter\\HTTP\\Response constructor expects CodeIgniter\\HTTP\\App, Config\\App given\.$#' + count: 1 + path: ../../tests/system/Test/TestResponseTest.php + - message: '#^Parameter \#3 \$errors of method CodeIgniter\\Validation\\Validation\:\:check\(\) expects list\, array\{is_numeric\: ''Nope\. Not a number\.''\} given\.$#' count: 1 diff --git a/utils/phpstan-baseline/empty.notAllowed.neon b/utils/phpstan-baseline/empty.notAllowed.neon index 827126f98676..796292761d9c 100644 --- a/utils/phpstan-baseline/empty.notAllowed.neon +++ b/utils/phpstan-baseline/empty.notAllowed.neon @@ -1,4 +1,4 @@ -# total 212 errors +# total 205 errors parameters: ignoreErrors: diff --git a/utils/phpstan-baseline/loader.neon b/utils/phpstan-baseline/loader.neon index 5214bfa1141b..1f2a49acb706 100644 --- a/utils/phpstan-baseline/loader.neon +++ b/utils/phpstan-baseline/loader.neon @@ -1,4 +1,4 @@ -# total 1819 errors +# total 1972 errors includes: - argument.type.neon