stored($theme); $defaults = collect($theme->settingsSchema()) ->mapWithKeys(fn ($definition, $key) => [$key => is_array($definition) ? ($definition['default'] ?? null) : $definition]) ->all(); return array_replace($defaults, array_diff_key((array) ($stored?->settings ?? []), array_flip([self::APPEARANCE_KEY, self::ACCENT_KEY]))); } public function variant(Theme $theme): string { $variant = (string) ($this->stored($theme)?->variant ?? array_key_first($theme->variants()) ?? 'light'); return array_key_exists($variant, $theme->variants()) ? $variant : (array_key_first($theme->variants()) ?? 'light'); } public function appearance(Theme $theme): string { $stored = (array) ($this->stored($theme)?->settings ?? []); $allowed = array_keys($theme->appearances()); if ($allowed === []) { return ''; } $appearance = (string) ($stored[self::APPEARANCE_KEY] ?? $theme->defaultAppearance()); return in_array($appearance, $allowed, true) ? $appearance : (string) array_key_first($theme->appearances()); } public function accent(Theme $theme): string { $stored = (array) ($this->stored($theme)?->settings ?? []); $allowed = array_keys($theme->accents()); if ($allowed === []) { return ''; } $accent = (string) ($stored[self::ACCENT_KEY] ?? $theme->defaultAccent()); return in_array($accent, $allowed, true) ? $accent : (string) array_key_first($theme->accents()); } public function save(Theme $theme, array $settings, string $variant, ?string $appearance = null, ?string $accent = null): ThemeSetting { $settings = array_intersect_key($settings, array_flip(array_keys($theme->settingsSchema()))); $existing = (array) ($this->stored($theme)?->settings ?? []); $allowedAppearances = array_keys($theme->appearances()); if ($allowedAppearances !== []) { $appearance ??= (string) ($existing[self::APPEARANCE_KEY] ?? $theme->defaultAppearance()); if (! in_array($appearance, $allowedAppearances, true)) { $appearance = (string) array_key_first($theme->appearances()); } $settings[self::APPEARANCE_KEY] = $appearance; } $allowedAccents = array_keys($theme->accents()); if ($allowedAccents !== []) { $accent ??= (string) ($existing[self::ACCENT_KEY] ?? $theme->defaultAccent()); if (! in_array($accent, $allowedAccents, true)) { $accent = (string) array_key_first($theme->accents()); } $settings[self::ACCENT_KEY] = $accent; } if ($theme->variants() && ! array_key_exists($variant, $theme->variants())) { $variant = array_key_first($theme->variants()); } return ThemeSetting::query()->updateOrCreate( ['theme_key' => $theme->key()], ['settings' => $settings, 'variant' => $variant] ); } private function stored(Theme $theme): ?ThemeSetting { try { return ThemeSetting::query()->where('theme_key', $theme->key())->first(); } catch (QueryException) { return null; } } }