From f8a195cbb2e8d0a3c3d8692c67edbfeef1c89d09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joachim=20R=C3=BCtter?= Date: Tue, 21 Jul 2026 10:21:39 +0200 Subject: [PATCH] Fix user column preferences being merged with defaults Co-Authored-By: Claude Fable 5 --- src/Preferences/Preferences.php | 25 ++++++++++++++++++++++++- tests/Preferences/PrecedenceTest.php | 22 ++++++++++++++++++++++ 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/src/Preferences/Preferences.php b/src/Preferences/Preferences.php index ff96e30a8e4..6c65cf425ad 100644 --- a/src/Preferences/Preferences.php +++ b/src/Preferences/Preferences.php @@ -140,7 +140,30 @@ protected function arrayDotPreferences($array) } } - return array_merge(Arr::dot($array), $preserve); + return array_merge($this->dotPreferences($array), $preserve); + } + + /** + * Flatten preferences into dotted keys, like `Arr::dot()`, but treating list values + * as leaves so they get replaced by higher precedence levels instead of merged. + * + * @param array $array + * @param string $prepend + * @return array + */ + protected function dotPreferences($array, $prepend = '') + { + $results = []; + + foreach ($array as $key => $value) { + if (is_array($value) && ! empty($value) && ! array_is_list($value)) { + $results = array_merge($results, $this->dotPreferences($value, $prepend.$key.'.')); + } else { + $results[$prepend.$key] = $value; + } + } + + return $results; } /** diff --git a/tests/Preferences/PrecedenceTest.php b/tests/Preferences/PrecedenceTest.php index 8622e7dd402..7e55277776e 100644 --- a/tests/Preferences/PrecedenceTest.php +++ b/tests/Preferences/PrecedenceTest.php @@ -245,6 +245,28 @@ public function it_gives_precedence_to_user_and_role_preferences_over_default_pr $this->assertTrue(Preference::get('deeply.nested.default')); } + #[Test] + public function it_replaces_list_preferences_instead_of_merging_them() + { + $this->actingAs(User::make()->preferences([ + 'collections' => [ + 'orders' => [ + 'columns' => ['date', 'title', 'customer'], + ], + ], + ])); + + Preference::default()->set([ + 'collections' => [ + 'orders' => [ + 'columns' => ['date', 'title', 'customer', 'grand_total', 'order_status'], + ], + ], + ])->save(); + + $this->assertEquals(['date', 'title', 'customer'], Preference::get('collections.orders.columns')); + } + #[Test] public function it_merges_preferences_at_every_level_unless_otherwise_configured() {