diff --git a/src/Fieldtypes/Range.php b/src/Fieldtypes/Range.php index a31482f6bc8..a15b0708423 100644 --- a/src/Fieldtypes/Range.php +++ b/src/Fieldtypes/Range.php @@ -18,19 +18,22 @@ protected function configFieldItems(): array 'min' => [ 'display' => __('Min'), 'instructions' => __('statamic::fieldtypes.range.config.min'), - 'type' => 'integer', + 'type' => 'text', + 'input_type' => 'number', 'default' => 0, ], 'max' => [ 'display' => __('Max'), 'instructions' => __('statamic::fieldtypes.range.config.max'), - 'type' => 'integer', + 'type' => 'text', + 'input_type' => 'number', 'default' => 100, ], 'step' => [ 'display' => __('Step'), 'instructions' => __('statamic::fieldtypes.range.config.step'), - 'type' => 'integer', + 'type' => 'text', + 'input_type' => 'number', 'default' => 1, ], 'default' => [ @@ -62,11 +65,33 @@ protected function configFieldItems(): array public function process($data) { + if ($this->usesDecimals()) { + return (float) $data; + } + return (int) $data; } + protected function usesDecimals(): bool + { + $step = $this->config('step', 1); + $min = $this->config('min', 0); + $max = $this->config('max', 100); + + return $this->isDecimal($step) || $this->isDecimal($min) || $this->isDecimal($max); + } + + protected function isDecimal($value): bool + { + if (! is_numeric($value)) { + return false; + } + + return floor((float) $value) != (float) $value; + } + public function toGqlType() { - return GraphQL::int(); + return $this->usesDecimals() ? GraphQL::float() : GraphQL::int(); } } diff --git a/tests/Feature/GraphQL/Fieldtypes/RangeFieldtypeTest.php b/tests/Feature/GraphQL/Fieldtypes/RangeFieldtypeTest.php index 9ee651bdb5f..dbb9f65e75f 100644 --- a/tests/Feature/GraphQL/Fieldtypes/RangeFieldtypeTest.php +++ b/tests/Feature/GraphQL/Fieldtypes/RangeFieldtypeTest.php @@ -9,16 +9,16 @@ class RangeFieldtypeTest extends FieldtypeTestCase { #[Test] - public function it_gets_an_integer() + public function it_processes_integer_values_with_integer_config() { $this->createEntryWithFields([ 'filled' => [ 'value' => '7', - 'field' => ['type' => 'range'], + 'field' => ['type' => 'range', 'min' => 0, 'max' => 100, 'step' => 1], ], 'undefined' => [ 'value' => null, - 'field' => ['type' => 'range'], + 'field' => ['type' => 'range', 'min' => 0, 'max' => 100, 'step' => 1], ], ]); @@ -27,4 +27,24 @@ public function it_gets_an_integer() 'undefined' => null, ]); } + + #[Test] + public function it_processes_decimal_values_with_decimal_config() + { + $this->createEntryWithFields([ + 'filled' => [ + 'value' => '7.5', + 'field' => ['type' => 'range', 'min' => 0, 'max' => 100, 'step' => 0.1], + ], + 'another' => [ + 'value' => '3.14', + 'field' => ['type' => 'range', 'min' => 0, 'max' => 10, 'step' => 0.01], + ], + ]); + + $this->assertGqlEntryHas('filled, another', [ + 'filled' => 7.5, + 'another' => 3.14, + ]); + } } diff --git a/tests/Fieldtypes/RangeFieldtypeTest.php b/tests/Fieldtypes/RangeFieldtypeTest.php new file mode 100644 index 00000000000..186a48f5089 --- /dev/null +++ b/tests/Fieldtypes/RangeFieldtypeTest.php @@ -0,0 +1,137 @@ +setField(new Field('test', [ + 'type' => 'range', + 'min' => 0, + 'max' => 100, + 'step' => 1, + ])); + + $result = $fieldtype->process('7'); + + $this->assertIsInt($result); + $this->assertEquals(7, $result); + } + + #[Test] + public function it_processes_as_float_with_decimal_step() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => 0, + 'max' => 100, + 'step' => 0.1, + ])); + + $result = $fieldtype->process('7.5'); + + $this->assertIsFloat($result); + $this->assertEquals(7.5, $result); + } + + #[Test] + public function it_processes_as_float_with_decimal_min() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => 0.5, + 'max' => 100, + 'step' => 1, + ])); + + $result = $fieldtype->process('7'); + + $this->assertIsFloat($result); + $this->assertEquals(7.0, $result); + } + + #[Test] + public function it_processes_as_float_with_decimal_max() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => 0, + 'max' => 99.9, + 'step' => 1, + ])); + + $result = $fieldtype->process('7'); + + $this->assertIsFloat($result); + $this->assertEquals(7.0, $result); + } + + #[Test] + public function it_processes_zero_as_integer_with_integer_config() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => 0, + 'max' => 100, + 'step' => 1, + ])); + + $result = $fieldtype->process('0'); + + $this->assertIsInt($result); + $this->assertEquals(0, $result); + } + + #[Test] + public function it_processes_negative_values_with_decimal_step() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => -10, + 'max' => 10, + 'step' => 0.5, + ])); + + $result = $fieldtype->process('-2.5'); + + $this->assertIsFloat($result); + $this->assertEquals(-2.5, $result); + } + + #[Test] + public function it_returns_int_graphql_type_with_integer_config() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => 0, + 'max' => 100, + 'step' => 1, + ])); + + $type = $fieldtype->toGqlType(); + + $this->assertEquals('Int', $type->name); + } + + #[Test] + public function it_returns_float_graphql_type_with_decimal_config() + { + $fieldtype = (new Range())->setField(new Field('test', [ + 'type' => 'range', + 'min' => 0, + 'max' => 100, + 'step' => 0.1, + ])); + + $type = $fieldtype->toGqlType(); + + $this->assertEquals('Float', $type->name); + } +}