From 61393850ab7d11f3ab4e9d842224e114e820d29c Mon Sep 17 00:00:00 2001 From: edalzell Date: Tue, 17 Mar 2026 13:39:52 -0700 Subject: [PATCH 1/3] computed default value --- src/Fields/Field.php | 17 +++++++++++++++++ src/Fields/Fields.php | 14 ++++++++++++++ tests/Fields/FieldTest.php | 26 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+) diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 634f03adff9..e187a11767c 100644 --- a/src/Fields/Field.php +++ b/src/Fields/Field.php @@ -297,9 +297,26 @@ public function value() public function defaultValue() { + if ($this->hasComputedDefault()) { + return Fields::resolveDefault(Str::chopStart($this->config['default'], 'computed:')); + } + return $this->config['default'] ?? $this->fieldtype()->defaultValue(); } + public function hasComputedDefault(): bool + { + if (! isset($this->config['default'])) { + return false; + } + + if (! is_string($this->config['default'])) { + return false; + } + + return Str::startsWith($this->config['default'], 'computed:'); + } + public function validationValue() { return $this->fieldtype()->validationValue($this->value); diff --git a/src/Fields/Fields.php b/src/Fields/Fields.php index 054c14361de..60bb1a5226f 100644 --- a/src/Fields/Fields.php +++ b/src/Fields/Fields.php @@ -2,6 +2,7 @@ namespace Statamic\Fields; +use Closure; use Facades\Statamic\Fields\FieldRepository; use Facades\Statamic\Fields\Validator; use Illuminate\Support\Collection; @@ -21,6 +22,19 @@ class Fields protected $withValidatableValues = false; protected $withComputedValues = false; + /** @var array */ + protected static array $computedFieldDefaultCallbacks = []; + + public static function default(string $key, Closure $callback): void + { + static::$computedFieldDefaultCallbacks[$key] = $callback; + } + + public static function resolveDefault(string $key): mixed + { + return static::$computedFieldDefaultCallbacks[$key](); + } + public function __construct($items = [], $parent = null, $parentField = null, $parentIndex = null) { $this diff --git a/tests/Fields/FieldTest.php b/tests/Fields/FieldTest.php index fe85243b090..6206d39a2fc 100644 --- a/tests/Fields/FieldTest.php +++ b/tests/Fields/FieldTest.php @@ -6,6 +6,7 @@ use PHPUnit\Framework\Attributes\Group; use PHPUnit\Framework\Attributes\Test; use Statamic\Fields\Field; +use Statamic\Fields\Fields; use Statamic\Fields\Fieldtype; use Statamic\Fields\Value; use Statamic\Forms\Form; @@ -474,6 +475,31 @@ public function defaultValue() $this->assertEquals('fieldtype defined default preprocessed', $field->preProcess()->value()); } + #[Test] + public function preprocessing_a_field_with_no_value_and_computed_default_value_will_use_the_computed_function() + { + FieldtypeRepository::shouldReceive('find') + ->with('fieldtype') + ->andReturn(new class extends Fieldtype + { + public function preProcess($data) + { + return $data.' preprocessed'; + } + + public function defaultValue() + { + return 'fieldtype defined default'; + } + }); + + Fields::default('computed-value', fn() => 'computed defined default'); + + $field = (new Field('test', ['default' => 'computed:computed-value', 'type' => 'fieldtype'])); + + $this->assertEquals('computed defined default preprocessed', $field->preProcess()->value()); + } + #[Test] public function converting_to_an_array_will_inline_the_handle() { From e586b139a5ea575bb65d20b5009677cdb3ddd017 Mon Sep 17 00:00:00 2001 From: edalzell Date: Tue, 17 Mar 2026 13:43:42 -0700 Subject: [PATCH 2/3] lint --- tests/Fields/FieldTest.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tests/Fields/FieldTest.php b/tests/Fields/FieldTest.php index 6206d39a2fc..a24c969321d 100644 --- a/tests/Fields/FieldTest.php +++ b/tests/Fields/FieldTest.php @@ -55,9 +55,7 @@ public function it_determines_if_localizable() #[Test] public function it_gets_the_fieldtype() { - $fieldtype = new class extends Fieldtype - { - }; + $fieldtype = new class extends Fieldtype {}; FieldtypeRepository::shouldReceive('find') ->with('the_fieldtype') @@ -295,6 +293,7 @@ public function converts_to_array_suitable_for_rendering_fields_in_publish_compo ->andReturn(new class extends Fieldtype { protected $component = 'example'; + protected $configFields = [ 'a_config_field_with_pre_processing' => ['type' => 'with_processing'], 'a_config_field_without_pre_processing' => ['type' => 'without_processing'], @@ -493,7 +492,7 @@ public function defaultValue() } }); - Fields::default('computed-value', fn() => 'computed defined default'); + Fields::default('computed-value', fn () => 'computed defined default'); $field = (new Field('test', ['default' => 'computed:computed-value', 'type' => 'fieldtype'])); From d1d5287ec5338dc51b4df4019cfe7bdae90fd991 Mon Sep 17 00:00:00 2001 From: edalzell Date: Tue, 17 Mar 2026 13:49:59 -0700 Subject: [PATCH 3/3] more lint --- tests/Fields/FieldTest.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/Fields/FieldTest.php b/tests/Fields/FieldTest.php index a24c969321d..cadb125ac93 100644 --- a/tests/Fields/FieldTest.php +++ b/tests/Fields/FieldTest.php @@ -55,7 +55,9 @@ public function it_determines_if_localizable() #[Test] public function it_gets_the_fieldtype() { - $fieldtype = new class extends Fieldtype {}; + $fieldtype = new class extends Fieldtype + { + }; FieldtypeRepository::shouldReceive('find') ->with('the_fieldtype')