Skip to content

Commit 81330b0

Browse files
ryanmitchellclaudejasonvarga
authored
[6.x] Ensure empty addon settings get default blueprint values (#14384)
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> Co-authored-by: Jason Varga <jason@pixelfear.com>
1 parent b490d6d commit 81330b0

2 files changed

Lines changed: 109 additions & 3 deletions

File tree

src/Addons/Settings.php

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ abstract class Settings implements Contract
1919
public function __construct(Addon $addon, array $settings = [])
2020
{
2121
$this->addon = $addon;
22-
$this->settings = $this->resolveAntlers($settings);
23-
$this->rawSettings = $settings;
22+
$this->setValues($settings);
2423
}
2524

2625
public function addon(): Addon
@@ -59,7 +58,7 @@ private function setValue(string $key, mixed $value): self
5958
private function setValues(array $values): self
6059
{
6160
$this->rawSettings = $values;
62-
$this->settings = $this->resolveAntlers($values);
61+
$this->settings = $this->resolveAntlers($this->applyBlueprintDefaults($values));
6362

6463
return $this;
6564
}
@@ -82,6 +81,20 @@ public function delete(): bool
8281
return app(SettingsRepository::class)->delete($this);
8382
}
8483

84+
private function applyBlueprintDefaults(array $settings): array
85+
{
86+
if (! $blueprint = $this->addon->settingsBlueprint()) {
87+
return $settings;
88+
}
89+
90+
$defaults = $blueprint->fields()->all()
91+
->mapWithKeys(fn ($field) => [$field->handle() => $field->defaultValue()])
92+
->whereNotNull()
93+
->all();
94+
95+
return array_merge($defaults, $settings);
96+
}
97+
8598
public function resolveAntlers($config)
8699
{
87100
return collect($config)

tests/Addons/SettingsTest.php

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,22 @@ public function it_sets_all_values()
146146
'test' => ['a' => 'A', 'b' => 'B'],
147147
'statamic.system.view_config_allowlist' => ['@default', 'test.a', 'test.b'],
148148
]);
149+
150+
$this->app->bind('statamic.addons.test-addon.settings_blueprint', fn () => [
151+
'tabs' => [
152+
'main' => [
153+
'sections' => [
154+
[
155+
'fields' => [
156+
['handle' => 'api_key', 'field' => ['type' => 'text', 'default' => 'my-default-key']],
157+
['handle' => 'another_field', 'field' => ['type' => 'text', 'default' => 'default-value']],
158+
],
159+
],
160+
],
161+
],
162+
],
163+
]);
164+
149165
$addon = $this->makeFromPackage();
150166
$settings = new Settings($addon, ['foo' => 'bar']);
151167

@@ -158,13 +174,90 @@ public function it_sets_all_values()
158174
]);
159175

160176
$this->assertEquals([
177+
'api_key' => 'my-default-key',
178+
'another_field' => 'default-value',
161179
'alfa' => 'bravo',
162180
'charlie' => 'A',
163181
'delta' => ['echo' => 'B'],
164182
], $settings->all());
165183
$this->assertEquals($raw, $settings->raw());
166184
}
167185

186+
#[Test]
187+
public function it_applies_blueprint_defaults_to_resolved_settings()
188+
{
189+
$this->app->bind('statamic.addons.test-addon.settings_blueprint', fn () => [
190+
'tabs' => [
191+
'main' => [
192+
'sections' => [
193+
[
194+
'fields' => [
195+
['handle' => 'api_key', 'field' => ['type' => 'text', 'default' => 'my-default-key']],
196+
['handle' => 'no_default_field', 'field' => ['type' => 'text']],
197+
],
198+
],
199+
],
200+
],
201+
],
202+
]);
203+
204+
$addon = $this->makeFromPackage();
205+
$settings = new Settings($addon, []);
206+
207+
$this->assertEquals('my-default-key', $settings->get('api_key'));
208+
$this->assertNull($settings->get('no_default_field'));
209+
}
210+
211+
#[Test]
212+
public function it_does_not_include_blueprint_defaults_in_raw_settings()
213+
{
214+
$this->app->bind('statamic.addons.test-addon.settings_blueprint', fn () => [
215+
'tabs' => [
216+
'main' => [
217+
'sections' => [
218+
[
219+
'fields' => [
220+
['handle' => 'api_key', 'field' => ['type' => 'text', 'default' => 'my-default-key']],
221+
],
222+
],
223+
],
224+
],
225+
],
226+
]);
227+
228+
$addon = $this->makeFromPackage();
229+
$settings = new Settings($addon, []);
230+
231+
$this->assertArrayNotHasKey('api_key', $settings->raw());
232+
$this->assertSame([], $settings->raw());
233+
}
234+
235+
#[Test]
236+
public function saved_settings_take_precedence_over_blueprint_defaults()
237+
{
238+
$this->app->bind('statamic.addons.test-addon.settings_blueprint', fn () => [
239+
'tabs' => [
240+
'main' => [
241+
'sections' => [
242+
[
243+
'fields' => [
244+
['handle' => 'api_key', 'field' => ['type' => 'text', 'default' => 'my-default-key']],
245+
['handle' => 'another_field', 'field' => ['type' => 'text', 'default' => 'default-value']],
246+
],
247+
],
248+
],
249+
],
250+
],
251+
]);
252+
253+
$addon = $this->makeFromPackage();
254+
$settings = new Settings($addon, ['api_key' => 'saved-key']);
255+
256+
$this->assertEquals('saved-key', $settings->get('api_key'));
257+
$this->assertEquals('default-value', $settings->get('another_field'));
258+
$this->assertSame(['api_key' => 'saved-key'], $settings->raw());
259+
}
260+
168261
#[Test]
169262
public function it_saves_settings()
170263
{

0 commit comments

Comments
 (0)