Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
79.55% |
35 / 44 |
|
66.67% |
2 / 3 |
CRAP | |
0.00% |
0 / 1 |
| SettingsController | |
79.55% |
35 / 44 |
|
66.67% |
2 / 3 |
28.93 | |
0.00% |
0 / 1 |
| index | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
| edit | |
100.00% |
7 / 7 |
|
100.00% |
1 / 1 |
1 | |||
| update | |
73.53% |
25 / 34 |
|
0.00% |
0 / 1 |
29.18 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace App\Http\Controllers\admin; |
| 4 | |
| 5 | use App\Http\Controllers\Controller; |
| 6 | use App\Services\Setting\SettingService; |
| 7 | use Illuminate\Http\RedirectResponse; |
| 8 | use Illuminate\Http\Request; |
| 9 | use Illuminate\Support\Str; |
| 10 | use Illuminate\View\View; |
| 11 | |
| 12 | /** |
| 13 | * The auto-generated settings screen. One tab per group in config/settings/*.php; |
| 14 | * fields, defaults and validation all come from the schema — this controller |
| 15 | * never names a setting. |
| 16 | */ |
| 17 | class SettingsController extends Controller |
| 18 | { |
| 19 | public function index(): RedirectResponse |
| 20 | { |
| 21 | $groups = array_keys(config('settings', ['general' => []])); |
| 22 | $first = in_array('general', $groups, true) ? 'general' : ($groups[0] ?? 'general'); |
| 23 | |
| 24 | return redirect()->route('admin.settings.edit', $first); |
| 25 | } |
| 26 | |
| 27 | public function edit(string $group): View |
| 28 | { |
| 29 | $groups = config('settings', []); |
| 30 | abort_unless(isset($groups[$group]), 404); |
| 31 | |
| 32 | return view('admin.settings.edit', [ |
| 33 | 'groups' => $groups, |
| 34 | 'active' => $group, |
| 35 | 'schema' => $groups[$group], |
| 36 | ]); |
| 37 | } |
| 38 | |
| 39 | public function update(Request $request, string $group, SettingService $settings): RedirectResponse |
| 40 | { |
| 41 | $schema = config("settings.{$group}"); |
| 42 | abort_unless($schema, 404); |
| 43 | |
| 44 | // Only touch the fields actually submitted (the form sends the whole |
| 45 | // group; a partial POST updates just what it carries). |
| 46 | $fields = collect($schema['fields'] ?? []) |
| 47 | ->only(array_keys($request->input($group, []))) |
| 48 | ->all(); |
| 49 | |
| 50 | // A toggle that is "off" submits only its hidden "0" companion, so a |
| 51 | // toggle field present in the schema but missing here is still a save. |
| 52 | foreach ($schema['fields'] ?? [] as $key => $def) { |
| 53 | if (($def['type'] ?? null) === 'toggle' && $request->has("{$group}") && ! array_key_exists($key, $fields)) { |
| 54 | $fields[$key] = $def; |
| 55 | } |
| 56 | } |
| 57 | |
| 58 | $rules = []; |
| 59 | foreach ($fields as $key => $def) { |
| 60 | if (! empty($def['rules'])) { |
| 61 | $rules["{$group}.{$key}"] = $def['rules']; |
| 62 | } |
| 63 | } |
| 64 | $validated = $request->validate($rules); |
| 65 | |
| 66 | foreach ($fields as $key => $def) { |
| 67 | $type = $def['type'] ?? 'text'; |
| 68 | |
| 69 | if ($type === 'media' && $request->hasFile("{$group}.{$key}_file")) { |
| 70 | $path = $request->file("{$group}.{$key}_file")->store('settings', 'public'); |
| 71 | $settings->set("{$group}.{$key}", 'storage/' . $path); |
| 72 | |
| 73 | continue; |
| 74 | } |
| 75 | |
| 76 | $value = data_get($validated, "{$group}.{$key}", $request->input("{$group}.{$key}")); |
| 77 | |
| 78 | $value = match ($type) { |
| 79 | 'toggle' => (bool) $value, |
| 80 | 'number' => $value === null || $value === '' ? null : $value + 0, |
| 81 | 'repeater' => collect(is_array($value) ? $value : []) |
| 82 | ->map(fn ($row) => array_map(fn ($v) => is_string($v) ? trim($v) : $v, (array) $row)) |
| 83 | ->reject(fn ($row) => count(array_filter($row, fn ($v) => $v !== '' && $v !== null)) === 0) |
| 84 | ->values() |
| 85 | ->all(), |
| 86 | default => is_string($value) ? trim($value) : $value, |
| 87 | }; |
| 88 | |
| 89 | $settings->set("{$group}.{$key}", $value === '' ? null : $value); |
| 90 | } |
| 91 | |
| 92 | return redirect() |
| 93 | ->route('admin.settings.edit', $group) |
| 94 | ->with('success', Str::headline($group) . ' settings saved.'); |
| 95 | } |
| 96 | } |