Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
79.55% covered (warning)
79.55%
35 / 44
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
SettingsController
79.55% covered (warning)
79.55%
35 / 44
66.67% covered (warning)
66.67%
2 / 3
28.93
0.00% covered (danger)
0.00%
0 / 1
 index
100.00% covered (success)
100.00%
3 / 3
100.00% covered (success)
100.00%
1 / 1
2
 edit
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
1
 update
73.53% covered (warning)
73.53%
25 / 34
0.00% covered (danger)
0.00%
0 / 1
29.18
1<?php
2
3namespace App\Http\Controllers\admin;
4
5use App\Http\Controllers\Controller;
6use App\Services\Setting\SettingService;
7use Illuminate\Http\RedirectResponse;
8use Illuminate\Http\Request;
9use Illuminate\Support\Str;
10use 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 */
17class 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}