diff --git a/CHANGELOG.md b/CHANGELOG.md index e1a5aeb..5f3ce76 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,12 @@ See [GitHub releases](https://github.com/mll-lab/laravel-utils/releases). ## Unreleased +## v5.2.0 + +### Added + +- Round floats in `UnsignedInt` cast + ## v5.1.0 ### Added diff --git a/php.dockerfile b/php.dockerfile index 74924c9..dc809b9 100644 --- a/php.dockerfile +++ b/php.dockerfile @@ -5,17 +5,18 @@ WORKDIR /workdir COPY --from=composer /usr/bin/composer /usr/bin/composer RUN apt-get update && \ - apt-get install -y \ + apt-get install --yes \ git \ libzip-dev \ zip \ libicu-dev \ + && rm -rf /var/lib/apt/lists/* \ && docker-php-ext-install \ + calendar \ zip \ mysqli \ pdo_mysql \ intl \ - && rm -rf /var/lib/apt/lists/* \ && pecl install \ xdebug \ redis \ diff --git a/src/Casts/UnsignedInt.php b/src/Casts/UnsignedInt.php index d83e6a7..4339352 100644 --- a/src/Casts/UnsignedInt.php +++ b/src/Casts/UnsignedInt.php @@ -21,9 +21,7 @@ class UnsignedInt implements CastsAttributes */ public function get($model, $key, $value, $attributes): int { - assert(is_int($value)); - - return max(0, $value); + return $this->cast($value); } /** @@ -33,7 +31,20 @@ public function get($model, $key, $value, $attributes): int */ public function set($model, $key, $value, $attributes): int { - assert(is_int($value)); + return $this->cast($value); + } + + protected function cast(mixed $value): int + { + if (is_float($value)) { + $value = (int) round($value); + } + + if (! is_int($value)) { + $type = gettype($value); + $valueString = var_export($value, true); + throw new \RuntimeException("Expected int, got {$type}: {$valueString}."); + } return max(0, $value); } diff --git a/tests/Casts/UnsignedIntTest.php b/tests/Casts/UnsignedIntTest.php index 1fe8fb8..8317f79 100644 --- a/tests/Casts/UnsignedIntTest.php +++ b/tests/Casts/UnsignedIntTest.php @@ -23,7 +23,19 @@ public function testCast(): void $model->unsigned_int = 2; self::assertSame(2, $model->getRawAttribute('unsigned_int')); + $model->unsigned_int = 2.4999; // @phpstan-ignore-line should round floats + self::assertSame(2, $model->getRawAttribute('unsigned_int')); + + $model->unsigned_int = 2.5001; // @phpstan-ignore-line should round floats + self::assertSame(3, $model->getRawAttribute('unsigned_int')); + $model->setRawAttribute('unsigned_int', -1); self::assertSame(0, $model->unsigned_int); + + $model->setRawAttribute('unsigned_int', 1.1); + self::assertSame(1, $model->unsigned_int); + + $this->expectExceptionObject(new \RuntimeException('Expected int, got string: "foo".')); + $model->unsigned_int = 'foo'; // @phpstan-ignore-line intentionally wrong } }