diff --git a/system/DataCaster/Cast/FloatCast.php b/system/DataCaster/Cast/FloatCast.php index d2173826265a..279fecaecc13 100644 --- a/system/DataCaster/Cast/FloatCast.php +++ b/system/DataCaster/Cast/FloatCast.php @@ -13,6 +13,8 @@ namespace CodeIgniter\DataCaster\Cast; +use CodeIgniter\DataCaster\Exceptions\CastException; + /** * Class FloatCast * @@ -30,6 +32,31 @@ public static function get( self::invalidTypeValueError($value); } - return (float) $value; + $precision = isset($params[0]) ? (int) $params[0] : null; + + if ($precision === null) { + return (float) $value; + } + + // Map string flags to PHP constants + $modeMap = [ + 'up' => PHP_ROUND_HALF_UP, + 'down' => PHP_ROUND_HALF_DOWN, + 'even' => PHP_ROUND_HALF_EVEN, + 'odd' => PHP_ROUND_HALF_ODD, + ]; + + $mode = PHP_ROUND_HALF_UP; // Default mode + + if (isset($params[1])) { + $modeParam = strtolower($params[1]); + if (isset($modeMap[$modeParam])) { + $mode = $modeMap[$modeParam]; + } else { + throw CastException::forInvalidFloatRoundingMode($params[1]); + } + } + + return round((float) $value, $precision, $mode); } } diff --git a/system/Entity/Exceptions/CastException.php b/system/Entity/Exceptions/CastException.php index 033f1ced478e..3bf48a2b1d05 100644 --- a/system/Entity/Exceptions/CastException.php +++ b/system/Entity/Exceptions/CastException.php @@ -122,4 +122,14 @@ public static function forInvalidEnumType(string $expectedClass, string $actualC { return new static(lang('Cast.enumInvalidType', [$actualClass, $expectedClass])); } + + /** + * Thrown when an invalid rounding mode is provided for float casting. + * + * @return static + */ + public static function forInvalidFloatRoundingMode(string $mode) + { + return new static(lang('Cast.floatInvalidRoundingMode', [$mode])); + } } diff --git a/tests/system/DataConverter/DataConverterTest.php b/tests/system/DataConverter/DataConverterTest.php index 220e101ba762..9e4bcc49c25b 100644 --- a/tests/system/DataConverter/DataConverterTest.php +++ b/tests/system/DataConverter/DataConverterTest.php @@ -197,6 +197,62 @@ public static function provideConvertDataFromDB(): iterable 'temp' => 15.9, ], ], + 'float precise' => [ + [ + 'id' => 'int', + 'temp' => 'float[2]', + ], + [ + 'id' => '1', + 'temp' => '15.98765', + ], + [ + 'id' => 1, + 'temp' => 15.99, + ], + ], + 'float precise-down' => [ + [ + 'id' => 'int', + 'temp' => 'float[2,down]', + ], + [ + 'id' => '1', + 'temp' => '1.235', + ], + [ + 'id' => 1, + 'temp' => 1.23, + ], + ], + 'float precise-even' => [ + [ + 'id' => 'int', + 'temp' => 'float[2,even]', + ], + [ + 'id' => '1', + 'temp' => '20.005', + ], + [ + 'id' => 1, + 'temp' => 20.00, + ], + ], + 'float precise-odd' => [ + [ + 'id' => 'int', + 'temp' => 'float[2,odd]', + ], + [ + 'id' => '1', + 'temp' => '1.255', + ], + [ + 'id' => 1, + 'temp' => 1.25, + ], + ], 'enum string-backed' => [ [ 'id' => 'int',