From 393181b26f9138ac4eb32a6df8e11cff4779727d Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:04:04 +0900 Subject: [PATCH 1/6] test: add test to pass Stringable to $db->escape() --- tests/system/Database/Live/EscapeTest.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index e1b700547c0c..e228c92aea06 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -14,6 +14,7 @@ namespace CodeIgniter\Database\Live; use CodeIgniter\Database\RawSql; +use CodeIgniter\I18n\Time; use CodeIgniter\Test\CIUnitTestCase; use CodeIgniter\Test\DatabaseTestTrait; @@ -54,6 +55,14 @@ public function testEscape(): void $this->assertSame($expected, $sql); } + public function testEscapeStringable(): void + { + $expected = "SELECT * FROM brands WHERE name = '2024-01-01 12:00:00'"; + $sql = 'SELECT * FROM brands WHERE name = ' . $this->db->escape(new Time('2024-01-01 12:00:00')); + + $this->assertSame($expected, $sql); + } + public function testEscapeString(): void { $expected = "SELECT * FROM brands WHERE name = 'O" . $this->char . "'Doules'"; From 4ac163dd5be369285339ad4e15b83f0b2885489c Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:04:44 +0900 Subject: [PATCH 2/6] fix: $db->escape() does not accept Stringable --- system/Database/BaseConnection.php | 8 ++++++-- system/Database/Postgre/Connection.php | 9 ++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index e0bd7bb51217..983e57ec6dda 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -17,6 +17,7 @@ use CodeIgniter\Database\Exceptions\DatabaseException; use CodeIgniter\Events\Events; use stdClass; +use Stringable; use Throwable; /** @@ -1309,12 +1310,15 @@ public function escape($str) return array_map($this->escape(...), $str); } - /** @psalm-suppress NoValue I don't know why ERROR. */ - if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) { + if ($str instanceof Stringable) { if ($str instanceof RawSql) { return $str->__toString(); } + $str = (string) $str; + } + + if (is_string($str)) { return "'" . $this->escapeString($str) . "'"; } diff --git a/system/Database/Postgre/Connection.php b/system/Database/Postgre/Connection.php index 45e30eb65365..bce4209c64d2 100644 --- a/system/Database/Postgre/Connection.php +++ b/system/Database/Postgre/Connection.php @@ -20,6 +20,7 @@ use PgSql\Connection as PgSqlConnection; use PgSql\Result as PgSqlResult; use stdClass; +use Stringable; /** * Connection for Postgre @@ -233,12 +234,15 @@ public function escape($str) $this->initialize(); } - /** @psalm-suppress NoValue I don't know why ERROR. */ - if (is_string($str) || (is_object($str) && method_exists($str, '__toString'))) { + if ($str instanceof Stringable) { if ($str instanceof RawSql) { return $str->__toString(); } + $str = (string) $str; + } + + if (is_string($str)) { return pg_escape_literal($this->connID, $str); } @@ -246,7 +250,6 @@ public function escape($str) return $str ? 'TRUE' : 'FALSE'; } - /** @psalm-suppress NoValue I don't know why ERROR. */ return parent::escape($str); } From 63a8aaa7e751528f1f45176c4d1c884a49370b3f Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:46:17 +0900 Subject: [PATCH 3/6] fix: $db->escapeString() does not accept Stringable --- system/Database/BaseConnection.php | 12 ++++++++++-- tests/system/Database/Live/EscapeTest.php | 18 ++++++++++++++++++ 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 983e57ec6dda..3847b92b255b 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1332,8 +1332,8 @@ public function escape($str) /** * Escape String * - * @param list|string $str Input string - * @param bool $like Whether or not the string will be used in a LIKE condition + * @param list|string|Stringable $str Input string + * @param bool $like Whether the string will be used in a LIKE condition * * @return list|string */ @@ -1347,6 +1347,14 @@ public function escapeString($str, bool $like = false) return $str; } + if ($str instanceof Stringable) { + if ($str instanceof RawSql) { + return $str->__toString(); + } + + $str = (string) $str; + } + $str = $this->_escapeString($str); // escape LIKE condition wildcards diff --git a/tests/system/Database/Live/EscapeTest.php b/tests/system/Database/Live/EscapeTest.php index e228c92aea06..0f931cdbe85c 100644 --- a/tests/system/Database/Live/EscapeTest.php +++ b/tests/system/Database/Live/EscapeTest.php @@ -71,6 +71,15 @@ public function testEscapeString(): void $this->assertSame($expected, $sql); } + public function testEscapeStringStringable(): void + { + $expected = "SELECT * FROM brands WHERE name = '2024-01-01 12:00:00'"; + $sql = "SELECT * FROM brands WHERE name = '" + . $this->db->escapeString(new Time('2024-01-01 12:00:00')) . "'"; + + $this->assertSame($expected, $sql); + } + public function testEscapeLikeString(): void { $expected = "SELECT * FROM brands WHERE column LIKE '%10!% more%' ESCAPE '!'"; @@ -79,6 +88,15 @@ public function testEscapeLikeString(): void $this->assertSame($expected, $sql); } + public function testEscapeLikeStringStringable(): void + { + $expected = "SELECT * FROM brands WHERE column LIKE '%2024-01-01 12:00:00%' ESCAPE '!'"; + $sql = "SELECT * FROM brands WHERE column LIKE '%" + . $this->db->escapeLikeString(new Time('2024-01-01 12:00:00')) . "%' ESCAPE '!'"; + + $this->assertSame($expected, $sql); + } + public function testEscapeLikeStringDirect(): void { if ($this->db->DBDriver === 'MySQLi') { From bd936e38f8a0288a8282078c3fb6b1b3b8133980 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 09:00:49 +0900 Subject: [PATCH 4/6] docs: update @param type --- system/Database/BaseConnection.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 3847b92b255b..b597c6d6cd10 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -1383,7 +1383,7 @@ public function escapeString($str, bool $like = false) * Calls the individual driver for platform * specific escaping for LIKE conditions * - * @param list|string $str + * @param list|string|Stringable $str * * @return list|string */ From 0337ce37a1b791f423a8c2c0bf4936092b8b78d1 Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:59:14 +0900 Subject: [PATCH 5/6] docs: replace @preperty with @property-read --- system/I18n/Time.php | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 2c6f3c4fab70..51d43a6486ab 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -21,22 +21,22 @@ * * Requires the intl PHP extension. * - * @property int $age read-only - * @property string $day read-only - * @property string $dayOfWeek read-only - * @property string $dayOfYear read-only - * @property bool $dst read-only - * @property string $hour read-only - * @property bool $local read-only - * @property string $minute read-only - * @property string $month read-only - * @property string $quarter read-only - * @property string $second read-only - * @property int $timestamp read-only - * @property bool $utc read-only - * @property string $weekOfMonth read-only - * @property string $weekOfYear read-only - * @property string $year read-only + * @property-read int $age + * @property-read string $day + * @property-read string $dayOfWeek + * @property-read string $dayOfYear + * @property-read bool $dst + * @property-read string $hour + * @property-read bool $local + * @property-read string $minute + * @property-read string $month + * @property-read string $quarter + * @property-read string $second + * @property-read int $timestamp + * @property-read bool $utc + * @property-read string $weekOfMonth + * @property-read string $weekOfYear + * @property-read string $year * * @see \CodeIgniter\I18n\TimeTest */ From c1ec70f2b4add77e1b8ec038ba2dd3c477aad1ba Mon Sep 17 00:00:00 2001 From: kenjis Date: Thu, 11 Apr 2024 08:59:38 +0900 Subject: [PATCH 6/6] refactor: implement Stringable To fix PHPStan errors. --- system/I18n/Time.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/system/I18n/Time.php b/system/I18n/Time.php index 51d43a6486ab..906479470b17 100644 --- a/system/I18n/Time.php +++ b/system/I18n/Time.php @@ -14,6 +14,7 @@ namespace CodeIgniter\I18n; use DateTimeImmutable; +use Stringable; /** * A localized date/time package inspired @@ -40,7 +41,7 @@ * * @see \CodeIgniter\I18n\TimeTest */ -class Time extends DateTimeImmutable +class Time extends DateTimeImmutable implements Stringable { use TimeTrait; }