diff --git a/src/Fields/Field.php b/src/Fields/Field.php index 45735cbda5b..f664e259fd0 100644 --- a/src/Fields/Field.php +++ b/src/Fields/Field.php @@ -22,6 +22,8 @@ */ class Field implements Arrayable { + const LISTED_BY_DEFAULT = ['title', 'slug', 'date', 'author']; + protected $handle; protected $prefix; protected $config; @@ -237,7 +239,7 @@ public function isListable() public function isVisibleOnListing() { if (is_null($this->get('listable'))) { - return in_array($this->handle, ['title', 'slug', 'date', 'author']); + return in_array($this->handle, self::LISTED_BY_DEFAULT); } return ! in_array($this->get('listable'), [false, 'hidden'], true); diff --git a/src/Fields/FieldTransformer.php b/src/Fields/FieldTransformer.php index 36d04352102..12248ea3e1c 100644 --- a/src/Fields/FieldTransformer.php +++ b/src/Fields/FieldTransformer.php @@ -35,11 +35,15 @@ private static function inlineTabField(array $submitted) ->merge($fieldtype->configFields()->all()); $field = collect($submitted['config']) - ->reject(function ($value, $key) use ($fields) { + ->reject(function ($value, $key) use ($fields, $submitted) { if ($key === 'isNew') { return true; } + if ($key === 'listable' && in_array($submitted['handle'], Field::LISTED_BY_DEFAULT)) { + return false; + } + if ($key === 'width' && $value === 100) { return true; } @@ -151,6 +155,7 @@ private static function referenceFieldToVue($field): array $mergedConfig['width'] = $mergedConfig['width'] ?? 100; $mergedConfig['localizable'] = $mergedConfig['localizable'] ?? false; + $mergedConfig = static::normalizeListable($mergedConfig, $field['handle']); return [ 'handle' => $field['handle'], @@ -170,6 +175,7 @@ private static function inlineFieldToVue($field): array $config['localizable'] = $config['localizable'] ?? false; $config = static::normalizeRequiredValidation($config); $config = static::normalizeVisibility($config); + $config = static::normalizeListable($config, $field['handle']); return [ 'handle' => $field['handle'], @@ -219,6 +225,15 @@ public static function fieldsetFields() return $fields; } + protected static function normalizeListable($config, $handle) + { + if (in_array($handle, Field::LISTED_BY_DEFAULT)) { + $config['listable'] ??= true; + } + + return $config; + } + protected static function normalizeRequiredValidation($config) { if (Arr::get($config, 'required') !== true) { diff --git a/tests/Fields/FieldTransformerTest.php b/tests/Fields/FieldTransformerTest.php index 442ffffc296..96ec6d6a809 100644 --- a/tests/Fields/FieldTransformerTest.php +++ b/tests/Fields/FieldTransformerTest.php @@ -2,6 +2,7 @@ namespace Tests\Fields; +use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Test; use Statamic\Facades\AssetContainer; use Statamic\Fields\Fieldset; @@ -418,4 +419,84 @@ public function it_supports_addon_linked_fields() 'localizable' => false, ], $this->configToVue('addon::some_fieldset.field1')); } + + #[Test] + #[DataProvider('listedByDefaultHandles')] + public function it_keeps_listable_hidden_for_fields_listed_by_default($handle) + { + $fromVue = FieldTransformer::fromVue([ + 'fieldtype' => 'text', + 'handle' => $handle, + 'type' => 'inline', + 'config' => ['listable' => 'hidden'], + ]); + + $this->assertEquals(['listable' => 'hidden'], $fromVue['field']); + } + + #[Test] + public function it_removes_listable_hidden_for_other_fields() + { + $fromVue = FieldTransformer::fromVue([ + 'fieldtype' => 'text', + 'handle' => 'test', + 'type' => 'inline', + 'config' => ['foo' => 'bar', 'listable' => 'hidden'], + ]); + + $this->assertEquals(['foo' => 'bar'], $fromVue['field']); + } + + #[Test] + #[DataProvider('listedByDefaultHandles')] + public function it_shows_fields_listed_by_default_as_listable($handle) + { + $config = FieldTransformer::toVue(['handle' => $handle, 'field' => []])['config']; + + $this->assertTrue($config['listable']); + } + + #[Test] + public function it_keeps_explicit_listable_for_fields_listed_by_default() + { + $config = FieldTransformer::toVue(['handle' => 'slug', 'field' => ['listable' => 'hidden']])['config']; + + $this->assertEquals('hidden', $config['listable']); + } + + #[Test] + public function it_doesnt_set_listable_for_other_fields() + { + $this->assertArrayNotHasKey('listable', $this->configToVue([])); + } + + #[Test] + public function it_shows_referenced_fields_listed_by_default_as_listable() + { + $fieldset = tap(new Fieldset) + ->setHandle('common') + ->setContents(['fields' => [ + [ + 'handle' => 'slug', + 'field' => ['type' => 'slug'], + ], + ]]); + + \Statamic\Facades\Fieldset::shouldReceive('all')->andReturn(collect(['common' => $fieldset])); + + $vue = FieldTransformer::toVue(['handle' => 'slug', 'field' => 'common.slug']); + + $this->assertTrue($vue['config']['listable']); + $this->assertEquals([], $vue['config_overrides']); + } + + public static function listedByDefaultHandles() + { + return [ + 'title' => ['title'], + 'slug' => ['slug'], + 'date' => ['date'], + 'author' => ['author'], + ]; + } }