diff --git a/lang/en/fieldtypes.php b/lang/en/fieldtypes.php index 650448ef7a..9c8001cc33 100644 --- a/lang/en/fieldtypes.php +++ b/lang/en/fieldtypes.php @@ -121,6 +121,7 @@ 'integer.title' => 'Integer', 'link.config.collections' => 'Entries from these collections will be available. Leaving this empty will make entries from routable collections available.', 'link.config.container' => 'Choose which asset container to use for this field.', + 'link.config.default_option' => 'The default Link type option, if available for the fieldtype\'s configuration.', 'link.title' => 'Link', 'list.config.add_row' => 'Customize the label of the "Add Item" button.', 'list.title' => 'List', diff --git a/src/Fieldtypes/Link.php b/src/Fieldtypes/Link.php index a42c37e7a9..d5ca420081 100644 --- a/src/Fieldtypes/Link.php +++ b/src/Fieldtypes/Link.php @@ -49,6 +49,21 @@ protected function configFieldItems(): array 'type' => 'toggle', 'width' => '50', ], + 'default_option' => [ + 'display' => __('Default Option'), + 'instructions' => __('statamic::fieldtypes.link.config.default_option'), + 'type' => 'select', + 'max_items' => 1, + 'width' => '50', + 'clearable' => true, + 'placeholder' => __('Default'), + 'options' => [ + 'asset' => __('Asset'), + 'entry' => __('Entry'), + 'first-child' => __('First Child'), + 'url' => __('URL'), + ], + ], ], ], ]; @@ -131,7 +146,18 @@ public function preload() private function initialOption($value, $entry, $asset) { if (! $value) { - return $this->field->isRequired() ? 'url' : null; + $fallback = $this->field->isRequired() ? 'url' : null; + $option = $this->field->get('default_option', $fallback); + + if ($option === 'first-child' && ! $this->showFirstChildOption()) { + return $fallback; + } + + if ($option === 'asset' && ! $this->showAssetOption()) { + return $fallback; + } + + return $option; } if ($value === '@child') { diff --git a/tests/Fieldtypes/LinkTest.php b/tests/Fieldtypes/LinkTest.php index be520a0262..8f57aec072 100644 --- a/tests/Fieldtypes/LinkTest.php +++ b/tests/Fieldtypes/LinkTest.php @@ -10,10 +10,13 @@ use Statamic\Fields\ArrayableString; use Statamic\Fields\Field; use Statamic\Fieldtypes\Link; +use Tests\PreventSavingStacheItemsToDisk; use Tests\TestCase; class LinkTest extends TestCase { + use PreventSavingStacheItemsToDisk; + #[Test] public function it_augments_string_to_string() { @@ -261,4 +264,106 @@ public function it_pre_processes_first_child_for_index_when_no_children() $this->assertNull($fieldtype->preProcessIndex('@child')); } + + #[Test] + public function it_preloads_the_configured_initial_option() + { + tap(Facades\Collection::make('pages')->routes('{slug}'))->sites(['en'])->save(); + + $field = new Field('test', [ + 'type' => 'link', + 'default_option' => 'entry', + ]); + + $field->setValue(null); + $fieldtype = (new Link)->setField($field); + + $this->assertEquals('entry', $fieldtype->preload()['initialOption']); + } + + #[Test] + public function it_preloads_the_url_initial_option_when_required() + { + tap(Facades\Collection::make('pages')->routes('{slug}'))->sites(['en'])->save(); + + $field = new Field('test', [ + 'type' => 'link', + 'required' => true, + ]); + + $field->setValue(null); + $fieldtype = (new Link)->setField($field); + + $this->assertEquals('url', $fieldtype->preload()['initialOption']); + } + + #[Test] + public function it_preloads_the_expected_initial_option_when_default_option_not_set() + { + tap(Facades\Collection::make('pages')->routes('{slug}'))->sites(['en'])->save(); + + $field = new Field('test', [ + 'type' => 'link', + ]); + + $field->setValue(null); + + $fieldtype = (new Link)->setField($field); + + $this->assertNull($fieldtype->preload()['initialOption']); + } + + #[Test] + public function it_preloads_initial_option_of_first_child_only_when_available() + { + tap(Facades\Collection::make('pages')->routes('{slug}'))->sites(['en'])->save(); + + $field = new Field('test', [ + 'type' => 'link', + 'default_option' => 'first-child', + 'required' => true, + ]); + + $field->setValue(null); + $field->setParent(Mockery::mock()); + + $fieldtype = (new Link)->setField($field); + + $this->assertEquals('url', $fieldtype->preload()['initialOption']); + } + + #[Test] + public function it_preloads_initial_option_of_asset_only_when_available() + { + tap(Facades\Collection::make('pages')->routes('{slug}'))->sites(['en'])->save(); + + $field = new Field('test', [ + 'type' => 'link', + 'default_option' => 'asset', + 'required' => true, + ]); + + $field->setValue(null); + + $fieldtype = (new Link)->setField($field); + + $this->assertEquals('url', $fieldtype->preload()['initialOption']); + } + + #[Test] + public function it_preloads_the_values_initial_option_when_set() + { + tap(Facades\Collection::make('pages')->routes('{slug}'))->sites(['en'])->save(); + + $field = new Field('test', [ + 'type' => 'link', + 'default_option' => 'entry', + ]); + + $field->setValue('https://example.com'); + + $fieldtype = (new Link)->setField($field); + + $this->assertEquals('url', $fieldtype->preload()['initialOption']); + } }