98 lines
3.6 KiB
PHP
98 lines
3.6 KiB
PHP
<?php
|
|
|
|
namespace Modules\Stylist\Services;
|
|
|
|
use Illuminate\Database\QueryException;
|
|
use Modules\Stylist\Models\ThemeSetting;
|
|
use Modules\Stylist\Theme\Theme;
|
|
|
|
final class ThemeSettings
|
|
{
|
|
private const APPEARANCE_KEY = '__stylist_appearance';
|
|
|
|
private const ACCENT_KEY = '__stylist_accent';
|
|
|
|
public function get(Theme $theme): array
|
|
{
|
|
$stored = $this->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;
|
|
}
|
|
}
|
|
}
|