Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,19 @@
</projectFiles>

<issueHandlers>
<!-- Psalm does not bring class-level template params into scope for static methods. -->
<NoValue>
<errorLevel type="suppress">
<directory name="system/DataCaster/Cast" />
<directory name="system/Entity/Cast" />
</errorLevel>
</NoValue>
<UndefinedDocblockClass>
<errorLevel type="suppress">
<directory name="system/DataCaster/Cast" />
<directory name="system/Entity/Cast" />
</errorLevel>
</UndefinedDocblockClass>
<UndefinedGlobalVariable>
<errorLevel type="suppress">
<directory name="tests/_support/View/Cells" />
Expand Down
6 changes: 3 additions & 3 deletions system/DataCaster/Cast/ArrayCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
namespace CodeIgniter\DataCaster\Cast;

/**
* Class ArrayCast
*
* (PHP) [array --> string] --> (DB driver) --> (DB column) string
* [ <-- string] <-- (DB driver) <-- (DB column) string
*
* @extends BaseCast<array<array-key, mixed>, string>
*/
class ArrayCast extends BaseCast implements CastInterface
class ArrayCast extends BaseCast
{
public static function get(
mixed $value,
Expand Down
6 changes: 6 additions & 0 deletions system/DataCaster/Cast/BaseCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,12 @@

use CodeIgniter\Exceptions\InvalidArgumentException;

/**
* @template TPhpNativeValue
* @template TDataSourceValue
*
* @implements CastInterface<TPhpNativeValue, TDataSourceValue>
*/
abstract class BaseCast implements CastInterface
{
public static function get(
Expand Down
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/BooleanCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
namespace CodeIgniter\DataCaster\Cast;

/**
* Class BooleanCast
*
* (PHP) [bool --> bool ] --> (DB driver) --> (DB column) bool|int(0/1)
* [ <-- string|int] <-- (DB driver) <-- (DB column) bool|int(0/1)
*
* @extends BaseCast<bool, mixed>
*/
class BooleanCast extends BaseCast
{
Expand Down
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/CSVCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
namespace CodeIgniter\DataCaster\Cast;

/**
* Class CSVCast
*
* (PHP) [array --> string] --> (DB driver) --> (DB column) string
* [ <-- string] <-- (DB driver) <-- (DB column) string
*
* @extends BaseCast<list<string>, string>
*/
class CSVCast extends BaseCast
{
Expand Down
28 changes: 12 additions & 16 deletions system/DataCaster/Cast/CastInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,35 +13,31 @@

namespace CodeIgniter\DataCaster\Cast;

/**
* @template TPhpNativeValue
* @template TDataSourceValue
*/
interface CastInterface
{
/**
* Takes a value from DataSource, returns its value for PHP.
* Takes a value from a data source, returns its value for PHP.
*
* @param mixed $value Data from database driver
* @param TDataSourceValue $value Data from database driver
* @param array<int, string> $params Additional param
* @param object|null $helper Helper object. E.g., database connection
*
* @return mixed PHP native value
* @return TPhpNativeValue
*/
public static function get(
mixed $value,
array $params = [],
?object $helper = null,
): mixed;
public static function get(mixed $value, array $params = [], ?object $helper = null): mixed;

/**
* Takes a PHP value, returns its value for DataSource.
* Takes a PHP value, returns its value for a data source.
*
* @param mixed $value PHP native value
* @param TPhpNativeValue $value PHP native value
* @param array<int, string> $params Additional param
* @param object|null $helper Helper object. E.g., database connection
*
* @return mixed Data to pass to database driver
* @return TDataSourceValue
*/
public static function set(
mixed $value,
array $params = [],
?object $helper = null,
): mixed;
public static function set(mixed $value, array $params = [], ?object $helper = null): mixed;
}
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/DatetimeCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
use CodeIgniter\I18n\Time;

/**
* Class DatetimeCast
*
* (PHP) [Time --> string] --> (DB driver) --> (DB column) datetime
* [ <-- string] <-- (DB driver) <-- (DB column) datetime
*
* @extends BaseCast<Time, string>
*/
class DatetimeCast extends BaseCast
{
Expand Down
22 changes: 5 additions & 17 deletions system/DataCaster/Cast/EnumCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@
use UnitEnum;

/**
* Class EnumCast
*
* Handles casting for PHP enums (both backed and unit enums)
*
* (PHP) [enum --> value/name] --> (DB driver) --> (DB column) int|string
* [ <-- value/name] <-- (DB driver) <-- (DB column) int|string
*
* @extends BaseCast<BackedEnum|UnitEnum, int|string>
*/
class EnumCast extends BaseCast implements CastInterface
class EnumCast extends BaseCast
{
public static function get(
mixed $value,
Expand All @@ -49,9 +49,7 @@ public static function get(

$reflection = new ReflectionEnum($enumClass);

// Unit enum
if (! $reflection->isBacked()) {
// Unit enum - match by name
if (! is_a($enumClass, BackedEnum::class, true)) {
foreach ($enumClass::cases() as $case) {
if ($case->name === $value) {
return $case;
Expand All @@ -61,10 +59,8 @@ public static function get(
throw CastException::forInvalidEnumCaseName($enumClass, $value);
}

// Backed enum - validate and cast the value to proper type
$backingType = $reflection->getBackingType();

// Cast to proper type (int or string)
if ($backingType->getName() === 'int') {
$value = (int) $value;
} elseif ($backingType->getName() === 'string') {
Expand All @@ -89,7 +85,6 @@ public static function set(
self::invalidTypeValueError($value);
}

// Get the expected enum class
$enumClass = $params[0] ?? null;

if ($enumClass === null) {
Expand All @@ -100,21 +95,14 @@ public static function set(
throw CastException::forNotEnum($enumClass);
}

// Validate that the enum is of the expected type
if (! $value instanceof $enumClass) {
throw CastException::forInvalidEnumType($enumClass, $value::class);
}

$reflection = new ReflectionEnum($value::class);

// Backed enum - return the properly typed backing value
if ($reflection->isBacked()) {
/** @var BackedEnum $value */
if ($value instanceof BackedEnum) {
return $value->value;
}

// Unit enum - return the case name
/** @var UnitEnum $value */
return $value->name;
}
}
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/FloatCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
namespace CodeIgniter\DataCaster\Cast;

/**
* Class FloatCast
*
* (PHP) [float --> float ] --> (DB driver) --> (DB column) float
* [ <-- float|string] <-- (DB driver) <-- (DB column) float
*
* @extends BaseCast<float, float|string>
*/
class FloatCast extends BaseCast
{
Expand Down
2 changes: 2 additions & 0 deletions system/DataCaster/Cast/IntBoolCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
*
* (PHP) [bool --> int ] --> (DB driver) --> (DB column) int(0/1)
* [ <-- int|string] <-- (DB driver) <-- (DB column) int(0/1)
*
* @extends BaseCast<bool, int>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @extends BaseCast<bool, int>
* @extends BaseCast<bool, int|string>

Strings are supported too.

*/
final class IntBoolCast extends BaseCast
{
Expand Down
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/IntegerCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@
namespace CodeIgniter\DataCaster\Cast;

/**
* Class IntegerCast
*
* (PHP) [int --> int ] --> (DB driver) --> (DB column) int
* [ <-- int|string] <-- (DB driver) <-- (DB column) int
*
* @extends BaseCast<int, int|string>
*/
class IntegerCast extends BaseCast
{
Expand Down
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/JsonCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@
use stdClass;

/**
* Class JsonCast
*
* (PHP) [array|stdClass --> string] --> (DB driver) --> (DB column) string
* [ <-- string] <-- (DB driver) <-- (DB column) string
*
* @extends BaseCast<array<array-key, mixed>|stdClass, string>
*/
class JsonCast extends BaseCast
{
Expand Down
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/TimestampCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
use CodeIgniter\I18n\Time;

/**
* Class TimestampCast
*
* (PHP) [Time --> int ] --> (DB driver) --> (DB column) int
* [ <-- int|string] <-- (DB driver) <-- (DB column) int
*
* @extends BaseCast<Time, int>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
* @extends BaseCast<Time, int>
* @extends BaseCast<Time, int|string>

We also support strings in the implementations.

*/
class TimestampCast extends BaseCast
{
Expand Down
4 changes: 2 additions & 2 deletions system/DataCaster/Cast/URICast.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
use CodeIgniter\HTTP\URI;

/**
* Class URICast
*
* (PHP) [URI --> string] --> (DB driver) --> (DB column) string
* [ <-- string] <-- (DB driver) <-- (DB column) string
*
* @extends BaseCast<URI, string>
*/
class URICast extends BaseCast
{
Expand Down
3 changes: 3 additions & 0 deletions system/Entity/Cast/ArrayCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

namespace CodeIgniter\Entity\Cast;

/**
* @extends BaseCast<array<array-key, mixed>, string>
*/
class ArrayCast extends BaseCast
{
public static function get($value, array $params = []): array
Expand Down
6 changes: 6 additions & 0 deletions system/Entity/Cast/BaseCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@

namespace CodeIgniter\Entity\Cast;

/**
* @template TPhpNativeValue
* @template TEntityStoredValue
*
* @implements CastInterface<TPhpNativeValue, TEntityStoredValue>
*/
abstract class BaseCast implements CastInterface
{
public static function get($value, array $params = [])
Expand Down
3 changes: 3 additions & 0 deletions system/Entity/Cast/BooleanCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

namespace CodeIgniter\Entity\Cast;

/**
* @extends BaseCast<bool, mixed>
*/
class BooleanCast extends BaseCast
{
public static function get($value, array $params = []): bool
Expand Down
3 changes: 3 additions & 0 deletions system/Entity/Cast/CSVCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@

namespace CodeIgniter\Entity\Cast;

/**
* @extends BaseCast<list<string>, string>
*/
class CSVCast extends BaseCast
{
public static function get($value, array $params = []): array
Expand Down
11 changes: 7 additions & 4 deletions system/Entity/Cast/CastInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,26 +17,29 @@
* The methods work at (1)(4) only.
* [App Code] --- (1) --> [Entity] --- (2) --> [Database]
* [App Code] <-- (4) --- [Entity] <-- (3) --- [Database]
*
* @template TPhpNativeValue
* @template TEntityStoredValue
*/
interface CastInterface
{
/**
* Takes a raw value from Entity, returns its value for PHP.
*
* @param mixed $value Data
* @param TEntityStoredValue $value
* @param array<int, string> $params Additional param
*
* @return mixed
* @return TPhpNativeValue
*/
public static function get($value, array $params = []);

/**
* Takes a PHP value, returns its raw value for Entity.
*
* @param mixed $value Data
* @param TPhpNativeValue $value
* @param array<int, string> $params Additional param
*
* @return mixed
* @return TEntityStoredValue
*/
public static function set($value, array $params = []);
}
11 changes: 3 additions & 8 deletions system/Entity/Cast/DatetimeCast.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,12 @@

use CodeIgniter\I18n\Time;
use DateTimeInterface;
use Exception;

/**
* @extends BaseCast<Time, DateTimeInterface|float|int|string>
*/
class DatetimeCast extends BaseCast
{
/**
* {@inheritDoc}
*
* @return Time
*
* @throws Exception
*/
public static function get($value, array $params = [])
{
if ($value instanceof Time) {
Expand Down
Loading
Loading