From de28579f14f4463590ddf2ff5da5bd4af1dd4608 Mon Sep 17 00:00:00 2001 From: neznaika0 Date: Wed, 1 Oct 2025 21:35:51 +0300 Subject: [PATCH 1/3] fix: TypeError in `DataCaster` init --- system/DataCaster/DataCaster.php | 26 ++++++++++++----- system/Entity/Cast/BaseCast.php | 18 +----------- tests/system/DataCaster/DataCasterTest.php | 34 ++++++++++++++++++++++ 3 files changed, 54 insertions(+), 24 deletions(-) create mode 100644 tests/system/DataCaster/DataCasterTest.php diff --git a/system/DataCaster/DataCaster.php b/system/DataCaster/DataCaster.php index 81ebe233c125..643e749647ec 100644 --- a/system/DataCaster/DataCaster.php +++ b/system/DataCaster/DataCaster.php @@ -28,6 +28,12 @@ use CodeIgniter\Entity\Exceptions\CastException; use CodeIgniter\Exceptions\InvalidArgumentException; +/** + * @template TCastHandlers of array + * + * @see CodeIgniter\DataCaster\DataCasterTest + * @see CodeIgniter\Entity\EntityTest + */ final class DataCaster { /** @@ -38,9 +44,9 @@ final class DataCaster private array $types = []; /** - * Convert handlers + * Convert handlers. * - * @var array [type => classname] + * @var TCastHandlers [type => classname] */ private array $castHandlers = [ 'array' => ArrayCast::class, @@ -59,10 +65,10 @@ final class DataCaster ]; /** - * @param array|null $castHandlers Custom convert handlers - * @param array|null $types [field => type] - * @param object|null $helper Helper object. - * @param bool $strict Strict mode? Set to false for casts for Entity. + * @param TCastHandlers|null $castHandlers Custom convert handlers + * @param array|null $types [field => type] + * @param object|null $helper Helper object. + * @param bool $strict Strict mode? Set to false for casts for Entity. */ public function __construct( ?array $castHandlers = null, @@ -70,7 +76,9 @@ public function __construct( private readonly ?object $helper = null, private readonly bool $strict = true, ) { - $this->castHandlers = array_merge($this->castHandlers, $castHandlers); + if ($castHandlers !== null && $castHandlers !== []) { + $this->castHandlers = array_merge($this->castHandlers, $castHandlers); + } if ($types !== null) { $this->setTypes($types); @@ -119,6 +127,10 @@ public function setTypes(array $types): static */ public function castAs(mixed $value, string $field, string $method = 'get'): mixed { + if ($method !== 'get' && $method !== 'set') { + throw CastException::forInvalidMethod($method); + } + // If the type is not defined, return as it is. if (! isset($this->types[$field])) { return $value; diff --git a/system/Entity/Cast/BaseCast.php b/system/Entity/Cast/BaseCast.php index 34cb28e787c5..a895952141dc 100644 --- a/system/Entity/Cast/BaseCast.php +++ b/system/Entity/Cast/BaseCast.php @@ -14,31 +14,15 @@ namespace CodeIgniter\Entity\Cast; /** - * Class BaseCast + * Class BaseCast. */ abstract class BaseCast implements CastInterface { - /** - * Get - * - * @param array|bool|float|int|object|string|null $value Data - * @param array $params Additional param - * - * @return array|bool|float|int|object|string|null - */ public static function get($value, array $params = []) { return $value; } - /** - * Set - * - * @param array|bool|float|int|object|string|null $value Data - * @param array $params Additional param - * - * @return array|bool|float|int|object|string|null - */ public static function set($value, array $params = []) { return $value; diff --git a/tests/system/DataCaster/DataCasterTest.php b/tests/system/DataCaster/DataCasterTest.php new file mode 100644 index 000000000000..7c1b3b47fa0e --- /dev/null +++ b/tests/system/DataCaster/DataCasterTest.php @@ -0,0 +1,34 @@ + + * + * For the full copyright and license information, please view + * the LICENSE file that was distributed with this source code. + */ + +namespace CodeIgniter\DataCaster; + +use CodeIgniter\Entity\Exceptions\CastException; +use CodeIgniter\Test\CIUnitTestCase; +use PHPUnit\Framework\Attributes\Group; + +/** + * @internal + */ +#[Group('Others')] +final class DataCasterTest extends CIUnitTestCase +{ + public function testCastInvalidMethodException(): void + { + $this->expectException(CastException::class); + $this->expectExceptionMessage('The "add" is invalid cast method, valid methods are: ["get", "set"].'); + + $dataCaster = new DataCaster(); + $dataCaster->castAs([], 'name', 'add'); // @phpstan-ignore argument.type + } +} From 6a131bda116a9d09d297b04958cf30bcc2ca726b Mon Sep 17 00:00:00 2001 From: neznaika0 Date: Sat, 4 Oct 2025 12:21:12 +0300 Subject: [PATCH 2/3] fix: Apply suggestion --- system/DataCaster/DataCaster.php | 24 +++++++++++----------- system/Entity/Cast/BaseCast.php | 3 --- tests/system/DataCaster/DataCasterTest.php | 2 +- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/system/DataCaster/DataCaster.php b/system/DataCaster/DataCaster.php index 643e749647ec..1d432179c129 100644 --- a/system/DataCaster/DataCaster.php +++ b/system/DataCaster/DataCaster.php @@ -29,7 +29,7 @@ use CodeIgniter\Exceptions\InvalidArgumentException; /** - * @template TCastHandlers of array + * @phpstan-type cast_handlers array * * @see CodeIgniter\DataCaster\DataCasterTest * @see CodeIgniter\Entity\EntityTest @@ -46,7 +46,8 @@ final class DataCaster /** * Convert handlers. * - * @var TCastHandlers [type => classname] + * @var array [type => classname] + * @phpstan-var cast_handlers */ private array $castHandlers = [ 'array' => ArrayCast::class, @@ -65,10 +66,11 @@ final class DataCaster ]; /** - * @param TCastHandlers|null $castHandlers Custom convert handlers - * @param array|null $types [field => type] - * @param object|null $helper Helper object. - * @param bool $strict Strict mode? Set to false for casts for Entity. + * @param array|null $castHandlers Custom convert handlers + * @param array|null $types [field => type] + * @param object|null $helper Helper object. + * @param bool $strict Strict mode? Set to false for casts for Entity. + * @phpstan-param cast_handlers|null $castHandlers */ public function __construct( ?array $castHandlers = null, @@ -76,9 +78,7 @@ public function __construct( private readonly ?object $helper = null, private readonly bool $strict = true, ) { - if ($castHandlers !== null && $castHandlers !== []) { - $this->castHandlers = array_merge($this->castHandlers, $castHandlers); - } + $this->castHandlers = array_merge($this->castHandlers, $castHandlers ?? []); if ($types !== null) { $this->setTypes($types); @@ -121,9 +121,9 @@ public function setTypes(array $types): static * Add ? at the beginning of the type (i.e. ?string) to get `null` * instead of casting $value when $value is null. * - * @param mixed $value The value to convert - * @param string $field The field name - * @param 'get'|'set' $method Allowed to "get" and "set" + * @param mixed $value The value to convert + * @param string $field The field name + * @param string $method Allowed to "get" and "set" */ public function castAs(mixed $value, string $field, string $method = 'get'): mixed { diff --git a/system/Entity/Cast/BaseCast.php b/system/Entity/Cast/BaseCast.php index a895952141dc..c93e32c0537c 100644 --- a/system/Entity/Cast/BaseCast.php +++ b/system/Entity/Cast/BaseCast.php @@ -13,9 +13,6 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class BaseCast. - */ abstract class BaseCast implements CastInterface { public static function get($value, array $params = []) diff --git a/tests/system/DataCaster/DataCasterTest.php b/tests/system/DataCaster/DataCasterTest.php index 7c1b3b47fa0e..89d3cbf40ea3 100644 --- a/tests/system/DataCaster/DataCasterTest.php +++ b/tests/system/DataCaster/DataCasterTest.php @@ -29,6 +29,6 @@ public function testCastInvalidMethodException(): void $this->expectExceptionMessage('The "add" is invalid cast method, valid methods are: ["get", "set"].'); $dataCaster = new DataCaster(); - $dataCaster->castAs([], 'name', 'add'); // @phpstan-ignore argument.type + $dataCaster->castAs([], 'name', 'add'); } } From cb3d4bfd979bbaefa7c94cb885baca30168ef89b Mon Sep 17 00:00:00 2001 From: neznaika0 Date: Sat, 4 Oct 2025 12:41:27 +0300 Subject: [PATCH 3/3] refactor: Remove unnecessary comments --- system/Entity/Cast/ArrayCast.php | 9 --------- system/Entity/Cast/BooleanCast.php | 6 ------ system/Entity/Cast/CSVCast.php | 9 --------- system/Entity/Cast/CastInterface.php | 2 -- system/Entity/Cast/DatetimeCast.php | 3 --- system/Entity/Cast/FloatCast.php | 6 ------ system/Entity/Cast/IntBoolCast.php | 2 -- system/Entity/Cast/IntegerCast.php | 6 ------ system/Entity/Cast/JsonCast.php | 6 ------ system/Entity/Cast/ObjectCast.php | 6 ------ system/Entity/Cast/StringCast.php | 6 ------ system/Entity/Cast/TimestampCast.php | 6 ------ system/Entity/Cast/URICast.php | 6 ------ 13 files changed, 73 deletions(-) diff --git a/system/Entity/Cast/ArrayCast.php b/system/Entity/Cast/ArrayCast.php index 1c810645dec6..6860b41416b6 100644 --- a/system/Entity/Cast/ArrayCast.php +++ b/system/Entity/Cast/ArrayCast.php @@ -13,14 +13,8 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class ArrayCast - */ class ArrayCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): array { if (is_string($value) && (str_starts_with($value, 'a:') || str_starts_with($value, 's:'))) { @@ -30,9 +24,6 @@ public static function get($value, array $params = []): array return (array) $value; } - /** - * {@inheritDoc} - */ public static function set($value, array $params = []): string { return serialize($value); diff --git a/system/Entity/Cast/BooleanCast.php b/system/Entity/Cast/BooleanCast.php index 8d95ba24b1de..7ac9f0ba37ee 100644 --- a/system/Entity/Cast/BooleanCast.php +++ b/system/Entity/Cast/BooleanCast.php @@ -13,14 +13,8 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class BooleanCast - */ class BooleanCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): bool { return (bool) $value; diff --git a/system/Entity/Cast/CSVCast.php b/system/Entity/Cast/CSVCast.php index 7b8be55d523c..c78a1315111a 100644 --- a/system/Entity/Cast/CSVCast.php +++ b/system/Entity/Cast/CSVCast.php @@ -13,22 +13,13 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class CSVCast - */ class CSVCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): array { return explode(',', $value); } - /** - * {@inheritDoc} - */ public static function set($value, array $params = []): string { return implode(',', $value); diff --git a/system/Entity/Cast/CastInterface.php b/system/Entity/Cast/CastInterface.php index 9d790e8edbb9..8f837fe8014c 100644 --- a/system/Entity/Cast/CastInterface.php +++ b/system/Entity/Cast/CastInterface.php @@ -14,8 +14,6 @@ namespace CodeIgniter\Entity\Cast; /** - * Interface CastInterface - * * The methods work at (1)(4) only. * [App Code] --- (1) --> [Entity] --- (2) --> [Database] * [App Code] <-- (4) --- [Entity] <-- (3) --- [Database] diff --git a/system/Entity/Cast/DatetimeCast.php b/system/Entity/Cast/DatetimeCast.php index 88b7b29267e0..72206ca883f7 100644 --- a/system/Entity/Cast/DatetimeCast.php +++ b/system/Entity/Cast/DatetimeCast.php @@ -17,9 +17,6 @@ use DateTime; use Exception; -/** - * Class DatetimeCast - */ class DatetimeCast extends BaseCast { /** diff --git a/system/Entity/Cast/FloatCast.php b/system/Entity/Cast/FloatCast.php index 642e849e747e..1a767c0953f0 100644 --- a/system/Entity/Cast/FloatCast.php +++ b/system/Entity/Cast/FloatCast.php @@ -13,14 +13,8 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class FloatCast - */ class FloatCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): float { return (float) $value; diff --git a/system/Entity/Cast/IntBoolCast.php b/system/Entity/Cast/IntBoolCast.php index fb1c470e892e..94e65df8dde0 100644 --- a/system/Entity/Cast/IntBoolCast.php +++ b/system/Entity/Cast/IntBoolCast.php @@ -14,8 +14,6 @@ namespace CodeIgniter\Entity\Cast; /** - * Int Bool Cast - * * DB column: int (0/1) <--> Class property: bool */ final class IntBoolCast extends BaseCast diff --git a/system/Entity/Cast/IntegerCast.php b/system/Entity/Cast/IntegerCast.php index c0ecec732436..84bf09211c0f 100644 --- a/system/Entity/Cast/IntegerCast.php +++ b/system/Entity/Cast/IntegerCast.php @@ -13,14 +13,8 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class IntegerCast - */ class IntegerCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): int { return (int) $value; diff --git a/system/Entity/Cast/JsonCast.php b/system/Entity/Cast/JsonCast.php index ef389269ede4..245de29f3956 100644 --- a/system/Entity/Cast/JsonCast.php +++ b/system/Entity/Cast/JsonCast.php @@ -17,14 +17,8 @@ use JsonException; use stdClass; -/** - * Class JsonCast - */ class JsonCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []) { $associative = in_array('array', $params, true); diff --git a/system/Entity/Cast/ObjectCast.php b/system/Entity/Cast/ObjectCast.php index 1bee213d50a7..10affad4c80c 100644 --- a/system/Entity/Cast/ObjectCast.php +++ b/system/Entity/Cast/ObjectCast.php @@ -13,14 +13,8 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class ObjectCast - */ class ObjectCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): object { return (object) $value; diff --git a/system/Entity/Cast/StringCast.php b/system/Entity/Cast/StringCast.php index e4ed04b94d95..d538f4332dca 100644 --- a/system/Entity/Cast/StringCast.php +++ b/system/Entity/Cast/StringCast.php @@ -13,14 +13,8 @@ namespace CodeIgniter\Entity\Cast; -/** - * Class StringCast - */ class StringCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): string { return (string) $value; diff --git a/system/Entity/Cast/TimestampCast.php b/system/Entity/Cast/TimestampCast.php index a445badec1f9..44bdf78864d1 100644 --- a/system/Entity/Cast/TimestampCast.php +++ b/system/Entity/Cast/TimestampCast.php @@ -15,14 +15,8 @@ use CodeIgniter\Entity\Exceptions\CastException; -/** - * Class TimestampCast - */ class TimestampCast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []) { $value = strtotime($value); diff --git a/system/Entity/Cast/URICast.php b/system/Entity/Cast/URICast.php index d0d510b10919..a66bfba3ef45 100644 --- a/system/Entity/Cast/URICast.php +++ b/system/Entity/Cast/URICast.php @@ -15,14 +15,8 @@ use CodeIgniter\HTTP\URI; -/** - * Class URICast - */ class URICast extends BaseCast { - /** - * {@inheritDoc} - */ public static function get($value, array $params = []): URI { return $value instanceof URI ? $value : new URI($value);