Skip to content

Commit 61aa099

Browse files
edalzellclaudejasonvarga
authored
[6.x] Default values can be computed (#14279)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent 81330b0 commit 61aa099

5 files changed

Lines changed: 84 additions & 0 deletions

File tree

src/Facades/Field.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace Statamic\Facades;
4+
5+
use Illuminate\Support\Facades\Facade;
6+
use Statamic\Fields\FieldRepository;
7+
8+
/**
9+
* @method static \Statamic\Fields\Field|null find(string $field)
10+
* @method static void computedDefault(string $key, \Closure $callback)
11+
* @method static mixed resolveComputedDefault(string $key, mixed $payload = null)
12+
*
13+
* @see FieldRepository
14+
*/
15+
class Field extends Facade
16+
{
17+
protected static function getFacadeAccessor()
18+
{
19+
return FieldRepository::class;
20+
}
21+
}

src/Fields/Field.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Support\Facades\Lang;
99
use Rebing\GraphQL\Support\Field as GqlField;
1010
use Statamic\Contracts\Forms\Form;
11+
use Statamic\Facades\Field as FieldFacade;
1112
use Statamic\Facades\GraphQL;
1213
use Statamic\Rules\Handle;
1314
use Statamic\Support\Arr;
@@ -297,9 +298,26 @@ public function value()
297298

298299
public function defaultValue()
299300
{
301+
if ($this->hasComputedDefault()) {
302+
return FieldFacade::resolveComputedDefault(Str::chopStart($this->config['default'], 'computed:'));
303+
}
304+
300305
return $this->config['default'] ?? $this->fieldtype()->defaultValue();
301306
}
302307

308+
public function hasComputedDefault(): bool
309+
{
310+
if (! isset($this->config['default'])) {
311+
return false;
312+
}
313+
314+
if (! is_string($this->config['default'])) {
315+
return false;
316+
}
317+
318+
return Str::startsWith($this->config['default'], 'computed:');
319+
}
320+
303321
public function validationValue()
304322
{
305323
return $this->fieldtype()->validationValue($this->value);

src/Fields/FieldRepository.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
namespace Statamic\Fields;
44

5+
use Closure;
56
use Statamic\Support\Str;
67

78
class FieldRepository
89
{
910
protected $fieldsets;
11+
protected $computedDefaultCallbacks = [];
1012

1113
public function __construct(FieldsetRepository $fieldsets)
1214
{
@@ -28,4 +30,18 @@ public function find(string $field): ?Field
2830

2931
return $fieldset->field($handle);
3032
}
33+
34+
public function computedDefault(string $key, Closure $callback): void
35+
{
36+
$this->computedDefaultCallbacks[$key] = $callback;
37+
}
38+
39+
public function resolveComputedDefault(string $key, mixed $payload = null): mixed
40+
{
41+
if (! array_key_exists($key, $this->computedDefaultCallbacks)) {
42+
throw new \RuntimeException("No computed default registered for key [{$key}].");
43+
}
44+
45+
return $this->computedDefaultCallbacks[$key]();
46+
}
3147
}

src/Providers/AppServiceProvider.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,8 @@ public function register()
193193
});
194194
});
195195

196+
$this->app->singleton(\Statamic\Fields\FieldRepository::class);
197+
196198
$this->app->singleton(\Statamic\Fields\FieldsetRepository::class, function () {
197199
return (new \Statamic\Fields\FieldsetRepository)
198200
->setDirectory(config('statamic.system.fieldsets_path'));

tests/Fields/FieldTest.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Facades\Statamic\Fields\FieldtypeRepository;
66
use PHPUnit\Framework\Attributes\Group;
77
use PHPUnit\Framework\Attributes\Test;
8+
use Statamic\Facades\Field as Fields;
89
use Statamic\Fields\Field;
910
use Statamic\Fields\Fieldtype;
1011
use Statamic\Fields\Value;
@@ -294,6 +295,7 @@ public function converts_to_array_suitable_for_rendering_fields_in_publish_compo
294295
->andReturn(new class extends Fieldtype
295296
{
296297
protected $component = 'example';
298+
297299
protected $configFields = [
298300
'a_config_field_with_pre_processing' => ['type' => 'with_processing'],
299301
'a_config_field_without_pre_processing' => ['type' => 'without_processing'],
@@ -474,6 +476,31 @@ public function defaultValue()
474476
$this->assertEquals('fieldtype defined default preprocessed', $field->preProcess()->value());
475477
}
476478

479+
#[Test]
480+
public function preprocessing_a_field_with_no_value_and_computed_default_value_will_use_the_computed_function()
481+
{
482+
FieldtypeRepository::shouldReceive('find')
483+
->with('fieldtype')
484+
->andReturn(new class extends Fieldtype
485+
{
486+
public function preProcess($data)
487+
{
488+
return $data.' preprocessed';
489+
}
490+
491+
public function defaultValue()
492+
{
493+
return 'fieldtype defined default';
494+
}
495+
});
496+
497+
Fields::computedDefault('computed-value', fn () => 'computed defined default');
498+
499+
$field = (new Field('test', ['default' => 'computed:computed-value', 'type' => 'fieldtype']));
500+
501+
$this->assertEquals('computed defined default preprocessed', $field->preProcess()->value());
502+
}
503+
477504
#[Test]
478505
public function converting_to_an_array_will_inline_the_handle()
479506
{

0 commit comments

Comments
 (0)