From 01ccd7d061e59a61dbd07da558b1613440f78170 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 15:45:39 +0900 Subject: [PATCH 1/4] refactor: fix variable type --- system/Email/Email.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Email/Email.php b/system/Email/Email.php index a6ad2d9932..ee29710bd9 100644 --- a/system/Email/Email.php +++ b/system/Email/Email.php @@ -898,7 +898,7 @@ class Email { $timezone = date('Z'); $operator = ($timezone[0] === '-') ? '-' : '+'; - $timezone = abs($timezone); + $timezone = abs((int) $timezone); $timezone = floor($timezone / 3600) * 100 + ($timezone % 3600) / 60; return sprintf('%s %s%04d', date('D, j M Y H:i:s'), $operator, $timezone); From 597101b98be62b5e8caa7468a9b541ae9074fb94 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 16:04:04 +0900 Subject: [PATCH 2/4] refactor: fix parameter types --- system/CLI/CLI.php | 6 +++--- system/Cache/ResponseCache.php | 2 +- system/CodeIgniter.php | 2 +- system/Database/BasePreparedQuery.php | 2 +- system/Database/Query.php | 2 +- system/Entity/Cast/DatetimeCast.php | 2 +- system/Format/XMLFormatter.php | 2 ++ system/HTTP/Files/FileCollection.php | 2 +- system/HTTP/ResponseInterface.php | 18 +++++++++--------- system/Helpers/number_helper.php | 4 ++-- system/Helpers/text_helper.php | 2 +- system/I18n/TimeTrait.php | 16 ++++++++-------- system/Images/Handlers/BaseHandler.php | 4 ++-- system/Router/RouteCollection.php | 4 ++-- system/Router/Router.php | 4 +++- system/View/Cell.php | 2 +- system/View/Filters.php | 8 ++++++-- 17 files changed, 45 insertions(+), 37 deletions(-) diff --git a/system/CLI/CLI.php b/system/CLI/CLI.php index 50a846a25e..ec30e9a55b 100644 --- a/system/CLI/CLI.php +++ b/system/CLI/CLI.php @@ -1066,7 +1066,7 @@ class CLI foreach ($tableRows[$row] as $col) { // Sets the size of this column in the current row - $allColsLengths[$row][$column] = static::strlen($col); + $allColsLengths[$row][$column] = static::strlen((string) $col); // If the current column does not have a value among the larger ones // or the value of this is greater than the existing one @@ -1086,7 +1086,7 @@ class CLI $column = 0; foreach ($tableRows[$row] as $col) { - $diff = $maxColsLengths[$column] - static::strlen($col); + $diff = $maxColsLengths[$column] - static::strlen((string) $col); if ($diff !== 0) { $tableRows[$row][$column] .= str_repeat(' ', $diff); @@ -1106,7 +1106,7 @@ class CLI $cols = '+'; foreach ($tableRows[$row] as $col) { - $cols .= str_repeat('-', static::strlen($col) + 2) . '+'; + $cols .= str_repeat('-', static::strlen((string) $col) + 2) . '+'; } $table .= $cols . PHP_EOL; } diff --git a/system/Cache/ResponseCache.php b/system/Cache/ResponseCache.php index 3f66284a6c..79948af10e 100644 --- a/system/Cache/ResponseCache.php +++ b/system/Cache/ResponseCache.php @@ -83,7 +83,7 @@ final class ResponseCache ? $uri->getQuery(is_array($this->cacheQueryString) ? ['only' => $this->cacheQueryString] : []) : ''; - return md5($uri->setFragment('')->setQuery($query)); + return md5((string) $uri->setFragment('')->setQuery($query)); } /** diff --git a/system/CodeIgniter.php b/system/CodeIgniter.php index c72a12bc07..45c6c958a4 100644 --- a/system/CodeIgniter.php +++ b/system/CodeIgniter.php @@ -744,7 +744,7 @@ class CodeIgniter ? $uri->getQuery(is_array($config->cacheQueryString) ? ['only' => $config->cacheQueryString] : []) : ''; - return md5($uri->setFragment('')->setQuery($query)); + return md5((string) $uri->setFragment('')->setQuery($query)); } /** diff --git a/system/Database/BasePreparedQuery.php b/system/Database/BasePreparedQuery.php index bfc0a608ea..22da47f990 100644 --- a/system/Database/BasePreparedQuery.php +++ b/system/Database/BasePreparedQuery.php @@ -175,7 +175,7 @@ abstract class BasePreparedQuery implements PreparedQueryInterface // Let others do something with this query Events::trigger('DBQuery', $query); - if ($this->db->isWriteType($query)) { + if ($this->db->isWriteType((string) $query)) { return true; } diff --git a/system/Database/Query.php b/system/Database/Query.php index a78190a217..897a668f13 100644 --- a/system/Database/Query.php +++ b/system/Database/Query.php @@ -357,7 +357,7 @@ class Query implements QueryInterface $escapedValue = '(' . implode(',', $escapedValue) . ')'; } - $sql = substr_replace($sql, $escapedValue, $matches[0][$c][1], $ml); + $sql = substr_replace($sql, (string) $escapedValue, $matches[0][$c][1], $ml); } while ($c !== 0); return $sql; diff --git a/system/Entity/Cast/DatetimeCast.php b/system/Entity/Cast/DatetimeCast.php index 423300cdae..5bfc533e08 100644 --- a/system/Entity/Cast/DatetimeCast.php +++ b/system/Entity/Cast/DatetimeCast.php @@ -38,7 +38,7 @@ class DatetimeCast extends BaseCast } if (is_numeric($value)) { - return Time::createFromTimestamp($value); + return Time::createFromTimestamp((int) $value); } if (is_string($value)) { diff --git a/system/Format/XMLFormatter.php b/system/Format/XMLFormatter.php index 51b3003e97..f1513ef661 100644 --- a/system/Format/XMLFormatter.php +++ b/system/Format/XMLFormatter.php @@ -91,6 +91,8 @@ class XMLFormatter implements FormatterInterface '\\x{FDF0}-\\x{FFFD}\\x{10000}-\\x{EFFFF}'; $validName = $startChar . '\\.\\d\\x{B7}\\x{300}-\\x{36F}\\x{203F}-\\x{2040}'; + $key = (string) $key; + $key = trim($key); $key = preg_replace("/[^{$validName}-]+/u", '', $key); $key = preg_replace("/^[^{$startChar}]+/u", 'item$0', $key); diff --git a/system/HTTP/Files/FileCollection.php b/system/HTTP/Files/FileCollection.php index f01cc69f59..88538513bb 100644 --- a/system/HTTP/Files/FileCollection.php +++ b/system/HTTP/Files/FileCollection.php @@ -185,7 +185,7 @@ class FileCollection $array['tmp_name'] ?? null, $array['name'] ?? null, $array['type'] ?? null, - $array['size'] ?? null, + ($array['size'] ?? null) === null ? null : (int) $array['size'], $array['error'] ?? null, $array['full_path'] ?? null ); diff --git a/system/HTTP/ResponseInterface.php b/system/HTTP/ResponseInterface.php index 9d3c8a9d64..d9a9fa574d 100644 --- a/system/HTTP/ResponseInterface.php +++ b/system/HTTP/ResponseInterface.php @@ -320,15 +320,15 @@ interface ResponseInterface extends MessageInterface * Accepts an arbitrary number of binds (up to 7) or an associative * array in the first parameter containing all the values. * - * @param array|string $name Cookie name or array containing binds - * @param string $value Cookie value - * @param int $expire Cookie expiration time in seconds - * @param string $domain Cookie domain (e.g.: '.yourdomain.com') - * @param string $path Cookie path (default: '/') - * @param string $prefix Cookie name prefix - * @param bool $secure Whether to only transfer cookies via SSL - * @param bool $httponly Whether only make the cookie accessible via HTTP (no javascript) - * @param string|null $samesite + * @param array|Cookie|string $name Cookie name / array containing binds / Cookie object + * @param string $value Cookie value + * @param int $expire Cookie expiration time in seconds + * @param string $domain Cookie domain (e.g.: '.yourdomain.com') + * @param string $path Cookie path (default: '/') + * @param string $prefix Cookie name prefix + * @param bool $secure Whether to only transfer cookies via SSL + * @param bool $httponly Whether only make the cookie accessible via HTTP (no javascript) + * @param string|null $samesite * * @return $this */ diff --git a/system/Helpers/number_helper.php b/system/Helpers/number_helper.php index 74173501e1..1b97d9a360 100644 --- a/system/Helpers/number_helper.php +++ b/system/Helpers/number_helper.php @@ -24,7 +24,7 @@ if (! function_exists('number_to_size')) { // Strip any formatting & ensure numeric input try { // @phpstan-ignore-next-line - $num = 0 + str_replace(',', '', $num); + $num = 0 + str_replace(',', '', (string) $num); } catch (ErrorException $ee) { // Catch "Warning: A non-numeric value encountered" return false; @@ -142,7 +142,7 @@ if (! function_exists('format_number')) { // Try to format it per the locale if ($type === NumberFormatter::CURRENCY) { - $formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, $options['fraction']); + $formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, (float) $options['fraction']); $output = $formatter->formatCurrency($num, $options['currency']); } else { // In order to specify a precision, we'll have to modify diff --git a/system/Helpers/text_helper.php b/system/Helpers/text_helper.php index 56cf856fbd..48e013826a 100755 --- a/system/Helpers/text_helper.php +++ b/system/Helpers/text_helper.php @@ -131,7 +131,7 @@ if (! function_exists('entities_to_ascii')) { { if (preg_match_all('/\&#(\d+)\;/', $str, $matches)) { for ($i = 0, $s = count($matches[0]); $i < $s; $i++) { - $digits = $matches[1][$i]; + $digits = (int) $matches[1][$i]; $out = ''; if ($digits < 128) { $out .= chr($digits); diff --git a/system/I18n/TimeTrait.php b/system/I18n/TimeTrait.php index 7f2068b7a3..ee491f2bc3 100644 --- a/system/I18n/TimeTrait.php +++ b/system/I18n/TimeTrait.php @@ -543,7 +543,7 @@ trait TimeTrait public function setMonth($value) { if (is_numeric($value) && ($value < 1 || $value > 12)) { - throw I18nException::forInvalidMonth($value); + throw I18nException::forInvalidMonth((string) $value); } if (is_string($value) && ! is_numeric($value)) { @@ -565,13 +565,13 @@ trait TimeTrait public function setDay($value) { if ($value < 1 || $value > 31) { - throw I18nException::forInvalidDay($value); + throw I18nException::forInvalidDay((string) $value); } $date = $this->getYear() . '-' . $this->getMonth(); $lastDay = date('t', strtotime($date)); if ($value > $lastDay) { - throw I18nException::forInvalidOverDay($lastDay, $value); + throw I18nException::forInvalidOverDay($lastDay, (string) $value); } return $this->setValue('day', $value); @@ -589,7 +589,7 @@ trait TimeTrait public function setHour($value) { if ($value < 0 || $value > 23) { - throw I18nException::forInvalidHour($value); + throw I18nException::forInvalidHour((string) $value); } return $this->setValue('hour', $value); @@ -607,7 +607,7 @@ trait TimeTrait public function setMinute($value) { if ($value < 0 || $value > 59) { - throw I18nException::forInvalidMinutes($value); + throw I18nException::forInvalidMinutes((string) $value); } return $this->setValue('minute', $value); @@ -625,7 +625,7 @@ trait TimeTrait public function setSecond($value) { if ($value < 0 || $value > 59) { - throw I18nException::forInvalidSeconds($value); + throw I18nException::forInvalidSeconds((string) $value); } return $this->setValue('second', $value); @@ -1008,7 +1008,7 @@ trait TimeTrait */ public function humanize() { - $now = IntlCalendar::fromDateTime(self::now($this->timezone)); + $now = IntlCalendar::fromDateTime(self::now($this->timezone)->toDateTime()); $time = $this->getCalendar()->getTime(); $years = $now->fieldDifference($time, IntlCalendar::FIELD_YEAR); @@ -1109,7 +1109,7 @@ trait TimeTrait */ public function getCalendar() { - return IntlCalendar::fromDateTime($this); + return IntlCalendar::fromDateTime($this->toDateTime()); } /** diff --git a/system/Images/Handlers/BaseHandler.php b/system/Images/Handlers/BaseHandler.php index cf23fd0fcd..fef31755aa 100644 --- a/system/Images/Handlers/BaseHandler.php +++ b/system/Images/Handlers/BaseHandler.php @@ -559,12 +559,12 @@ abstract class BaseHandler implements ImageHandlerInterface [$cropWidth, $cropHeight] = $this->calcAspectRatio($width, $height, $origWidth, $origHeight); if ($height === null) { - $height = ceil(($width / $cropWidth) * $cropHeight); + $height = (int) ceil(($width / $cropWidth) * $cropHeight); } [$x, $y] = $this->calcCropCoords($cropWidth, $cropHeight, $origWidth, $origHeight, $position); - return $this->crop($cropWidth, $cropHeight, $x, $y)->resize($width, $height); + return $this->crop($cropWidth, $cropHeight, (int) $x, (int) $y)->resize($width, $height); } /** diff --git a/system/Router/RouteCollection.php b/system/Router/RouteCollection.php index 91cb99ce8d..ea019f8b0c 100644 --- a/system/Router/RouteCollection.php +++ b/system/Router/RouteCollection.php @@ -1367,14 +1367,14 @@ class RouteCollection implements RouteCollectionInterface // or maybe $placeholder is not a placeholder, but a regex. $pattern = $this->placeholders[$placeholderName] ?? $placeholder; - if (! preg_match('#^' . $pattern . '$#u', $params[$index])) { + if (! preg_match('#^' . $pattern . '$#u', (string) $params[$index])) { throw RouterException::forInvalidParameterType(); } // Ensure that the param we're inserting matches // the expected param type. $pos = strpos($from, $placeholder); - $from = substr_replace($from, $params[$index], $pos, strlen($placeholder)); + $from = substr_replace($from, (string) $params[$index], $pos, strlen($placeholder)); } $from = $this->replaceLocale($from, $locale); diff --git a/system/Router/Router.php b/system/Router/Router.php index 3e2f504b38..7f26cf3b12 100644 --- a/system/Router/Router.php +++ b/system/Router/Router.php @@ -382,7 +382,9 @@ class Router implements RouterInterface foreach ($routes as $routeKey => $handler) { $routeKey = $routeKey === '/' ? $routeKey - : ltrim($routeKey, '/ '); + // $routeKey may be int, because it is an array key, + // and the URI `/1` is valid. The leading `/` is removed. + : ltrim((string) $routeKey, '/ '); $matchedKey = $routeKey; diff --git a/system/View/Cell.php b/system/View/Cell.php index f654e97a37..4031ab63f5 100644 --- a/system/View/Cell.php +++ b/system/View/Cell.php @@ -209,7 +209,7 @@ class Cell $publicParams = array_intersect_key($params, $publicProperties); foreach ($params as $key => $value) { - $getter = 'get' . ucfirst($key) . 'Property'; + $getter = 'get' . ucfirst((string) $key) . 'Property'; if (in_array($key, $privateProperties, true) && method_exists($instance, $getter)) { $publicParams[$key] = $value; } diff --git a/system/View/Filters.php b/system/View/Filters.php index 65dfe6dff9..379ccac186 100644 --- a/system/View/Filters.php +++ b/system/View/Filters.php @@ -38,6 +38,10 @@ class Filters $value = strtotime($value); } + if ($value !== null) { + $value = (int) $value; + } + return date($format, $value); } @@ -158,7 +162,7 @@ class Filters 'duration' => NumberFormatter::DURATION, ]; - return format_number($value, $precision, $locale, ['type' => $types[$type]]); + return format_number((float) $value, $precision, $locale, ['type' => $types[$type]]); } /** @@ -179,7 +183,7 @@ class Filters 'fraction' => $fraction, ]; - return format_number($value, 2, $locale, $options); + return format_number((float) $value, 2, $locale, $options); } /** From 78dc6456e4540c3e353aa476c46b05a33fc3be70 Mon Sep 17 00:00:00 2001 From: kenjis Date: Sun, 22 Oct 2023 17:26:09 +0900 Subject: [PATCH 3/4] refactor: fix return type --- system/Helpers/html_helper.php | 2 +- system/View/Parser.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/system/Helpers/html_helper.php b/system/Helpers/html_helper.php index c7a36e2708..7a76434d0e 100755 --- a/system/Helpers/html_helper.php +++ b/system/Helpers/html_helper.php @@ -179,7 +179,7 @@ if (! function_exists('doctype')) { $config = new DocTypes(); $doctypes = $config->list; - return $doctypes[$type] ?? false; + return $doctypes[$type] ?? ''; } } diff --git a/system/View/Parser.php b/system/View/Parser.php index a948579e8f..adeb01cae6 100644 --- a/system/View/Parser.php +++ b/system/View/Parser.php @@ -619,7 +619,7 @@ class Parser extends View $replace = $this->config->filters[$filter]($replace, ...$param); } - return $replace; + return (string) $replace; } // Plugins From f8c8ca52ffbb7e7dd273d5a2e8c5291bc91cb078 Mon Sep 17 00:00:00 2001 From: kenjis Date: Wed, 25 Oct 2023 12:04:59 +0900 Subject: [PATCH 4/4] test: fix param types --- tests/system/Commands/ClearDebugbarTest.php | 2 +- tests/system/CommonFunctionsSendTest.php | 2 +- tests/system/CommonFunctionsTest.php | 2 +- tests/system/Debug/Toolbar/Collectors/HistoryTest.php | 2 +- tests/system/HTTP/ResponseSendTest.php | 4 +++- tests/system/HTTP/ResponseTest.php | 2 +- tests/system/Helpers/CookieHelperTest.php | 4 +++- tests/system/Helpers/FilesystemHelperTest.php | 2 +- tests/system/Helpers/TextHelperTest.php | 2 +- 9 files changed, 13 insertions(+), 9 deletions(-) diff --git a/tests/system/Commands/ClearDebugbarTest.php b/tests/system/Commands/ClearDebugbarTest.php index b8f6fa13e5..f3062d9d5a 100644 --- a/tests/system/Commands/ClearDebugbarTest.php +++ b/tests/system/Commands/ClearDebugbarTest.php @@ -39,7 +39,7 @@ final class ClearDebugbarTest extends CIUnitTestCase // create 10 dummy debugbar json files for ($i = 0; $i < 10; $i++) { - $path = str_replace($time, $time - $i, $path); + $path = str_replace((string) $time, (string) ($time - $i), $path); file_put_contents($path, "{}\n"); $time -= $i; diff --git a/tests/system/CommonFunctionsSendTest.php b/tests/system/CommonFunctionsSendTest.php index a580366277..4e88dd9664 100644 --- a/tests/system/CommonFunctionsSendTest.php +++ b/tests/system/CommonFunctionsSendTest.php @@ -43,7 +43,7 @@ final class CommonFunctionsSendTest extends CIUnitTestCase $response = redirect()->route('login') ->setCookie('foo', 'onething', YEAR) - ->setCookie('login_time', $loginTime, YEAR); + ->setCookie('login_time', (string) $loginTime, YEAR); $response->pretend(false); $this->assertTrue($response->hasCookie('foo', 'onething')); $this->assertTrue($response->hasCookie('login_time')); diff --git a/tests/system/CommonFunctionsTest.php b/tests/system/CommonFunctionsTest.php index b6702c5a73..15c52896a1 100644 --- a/tests/system/CommonFunctionsTest.php +++ b/tests/system/CommonFunctionsTest.php @@ -576,7 +576,7 @@ final class CommonFunctionsTest extends CIUnitTestCase $answer1 = redirect()->route('login') ->setCookie('foo', 'onething', YEAR) - ->setCookie('login_time', $loginTime, YEAR); + ->setCookie('login_time', (string) $loginTime, YEAR); $this->assertTrue($answer1->hasCookie('foo', 'onething')); $this->assertTrue($answer1->hasCookie('login_time')); diff --git a/tests/system/Debug/Toolbar/Collectors/HistoryTest.php b/tests/system/Debug/Toolbar/Collectors/HistoryTest.php index 1286a489b1..8e056fbc75 100644 --- a/tests/system/Debug/Toolbar/Collectors/HistoryTest.php +++ b/tests/system/Debug/Toolbar/Collectors/HistoryTest.php @@ -61,7 +61,7 @@ final class HistoryTest extends CIUnitTestCase // create 20 dummy debugbar json files for ($i = 0; $i < 20; $i++) { - $path = str_replace($time, sprintf('%.6f', $time - self::STEP), $path); + $path = str_replace((string) $time, sprintf('%.6f', $time - self::STEP), $path); file_put_contents($path, json_encode($dummyData)); $time = sprintf('%.6f', $time - self::STEP); } diff --git a/tests/system/HTTP/ResponseSendTest.php b/tests/system/HTTP/ResponseSendTest.php index 437d379fdf..f1ceac8cd7 100644 --- a/tests/system/HTTP/ResponseSendTest.php +++ b/tests/system/HTTP/ResponseSendTest.php @@ -127,9 +127,11 @@ final class ResponseSendTest extends CIUnitTestCase $answer1 = $response->redirect('/login') ->setCookie('foo', 'bar', YEAR) - ->setCookie('login_time', $loginTime, YEAR); + ->setCookie('login_time', (string) $loginTime, YEAR); + $this->assertTrue($answer1->hasCookie('foo', 'bar')); $this->assertTrue($answer1->hasCookie('login_time')); + $response->setBody('Hello'); // send it diff --git a/tests/system/HTTP/ResponseTest.php b/tests/system/HTTP/ResponseTest.php index e08dc1de62..212ad674b4 100644 --- a/tests/system/HTTP/ResponseTest.php +++ b/tests/system/HTTP/ResponseTest.php @@ -551,7 +551,7 @@ final class ResponseTest extends CIUnitTestCase $response = new Response(new App()); $answer1 = $response->redirect('/login') ->setCookie('foo', 'bar', YEAR) - ->setCookie('login_time', $loginTime, YEAR); + ->setCookie('login_time', (string) $loginTime, YEAR); $this->assertTrue($answer1->hasCookie('foo')); $this->assertTrue($answer1->hasCookie('login_time')); diff --git a/tests/system/Helpers/CookieHelperTest.php b/tests/system/Helpers/CookieHelperTest.php index 45796658fe..51a00b6ba0 100755 --- a/tests/system/Helpers/CookieHelperTest.php +++ b/tests/system/Helpers/CookieHelperTest.php @@ -250,10 +250,12 @@ final class CookieHelperTest extends CIUnitTestCase public function testSameSiteParam(): void { - set_cookie($this->name, $this->value, $this->expire, '', '', '', '', '', 'Strict'); + set_cookie($this->name, $this->value, $this->expire, '', '', '', null, null, 'Strict'); $this->assertTrue($this->response->hasCookie($this->name)); + $theCookie = $this->response->getCookie($this->name); + $this->assertSame('Strict', $theCookie->getSameSite()); delete_cookie($this->name); diff --git a/tests/system/Helpers/FilesystemHelperTest.php b/tests/system/Helpers/FilesystemHelperTest.php index e92505cc8a..af682c459f 100644 --- a/tests/system/Helpers/FilesystemHelperTest.php +++ b/tests/system/Helpers/FilesystemHelperTest.php @@ -92,7 +92,7 @@ final class FilesystemHelperTest extends CIUnitTestCase $root = vfsStream::setup('root', null, $this->structure); $this->assertTrue($root->hasChild('foo')); - $this->assertSame($expected, directory_map(vfsStream::url('root'), false, true)); + $this->assertSame($expected, directory_map(vfsStream::url('root'), 0, true)); } public function testDirectoryMapLimitsRecursion(): void diff --git a/tests/system/Helpers/TextHelperTest.php b/tests/system/Helpers/TextHelperTest.php index 2af7f13875..20647ec783 100755 --- a/tests/system/Helpers/TextHelperTest.php +++ b/tests/system/Helpers/TextHelperTest.php @@ -136,7 +136,7 @@ final class TextHelperTest extends CIUnitTestCase $this->assertSame('file_5', increment_string('file_4')); $this->assertSame('file-5', increment_string('file-4', '-')); $this->assertSame('file-5', increment_string('file-4', '-')); - $this->assertSame('file-1', increment_string('file', '-', '1')); + $this->assertSame('file-1', increment_string('file', '-', 1)); $this->assertSame('124', increment_string('123', '')); }