Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
| Total | |
92.00% |
46 / 50 |
|
75.00% |
3 / 4 |
CRAP | |
0.00% |
0 / 1 |
| NotificationSettingsController | |
92.00% |
46 / 50 |
|
75.00% |
3 / 4 |
9.04 | |
0.00% |
0 / 1 |
| index | |
100.00% |
24 / 24 |
|
100.00% |
1 / 1 |
1 | |||
| updateChannel | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
4 | |||
| updateEvent | |
100.00% |
11 / 11 |
|
100.00% |
1 / 1 |
1 | |||
| sendTest | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
12 | |||
| 1 | <?php |
| 2 | |
| 3 | namespace App\Http\Controllers\admin; |
| 4 | |
| 5 | use App\Http\Controllers\Controller; |
| 6 | use App\Models\NotificationLog; |
| 7 | use App\Services\Notification\NotificationManager; |
| 8 | use Illuminate\Http\RedirectResponse; |
| 9 | use Illuminate\Http\Request; |
| 10 | use Illuminate\View\View; |
| 11 | |
| 12 | /** |
| 13 | * Settings → Notification Settings. Two things live here: |
| 14 | * - channel cards (enable toggle + credentials), same pattern as |
| 15 | * Settings → Payment Gateways (PaymentGatewayController); |
| 16 | * - the event × channel matrix + per-event subject/body templates |
| 17 | * (config/notification_events.php rows). |
| 18 | * A fresh install sends nothing: every channel starts off, and every |
| 19 | * event's channel list starts empty even once a channel is configured. |
| 20 | */ |
| 21 | class NotificationSettingsController extends Controller |
| 22 | { |
| 23 | public function index(NotificationManager $manager): View |
| 24 | { |
| 25 | $channels = collect($manager->keys())->map(function ($key) use ($manager) { |
| 26 | $driver = $manager->driver($key); |
| 27 | $entry = config("notification_channels.{$key}"); |
| 28 | |
| 29 | return [ |
| 30 | 'key' => $key, |
| 31 | 'label' => $driver->label(), |
| 32 | 'schema' => $driver->configSchema(), |
| 33 | 'group' => $entry['group'], |
| 34 | 'feature' => $entry['feature'], |
| 35 | 'isImplemented' => $driver->isImplemented(), |
| 36 | 'enabled' => settings("notification_channels.{$key}.enabled", $entry['default_enabled'] ?? false), |
| 37 | 'config' => $manager->config($key), |
| 38 | ]; |
| 39 | })->groupBy('group'); |
| 40 | |
| 41 | $events = collect(config('notification_events'))->map(function ($event, $key) { |
| 42 | return array_merge($event, [ |
| 43 | 'key' => $key, |
| 44 | 'channels' => (array) settings("notifications.{$key}.channels", []), |
| 45 | 'subject' => settings("notifications.{$key}.subject", $event['default_subject']), |
| 46 | 'body' => settings("notifications.{$key}.body", $event['default_body']), |
| 47 | ]); |
| 48 | }); |
| 49 | |
| 50 | $recentLog = NotificationLog::query()->latest()->limit(20)->get(); |
| 51 | |
| 52 | return view('admin.notification-settings.index', compact('channels', 'events', 'recentLog')); |
| 53 | } |
| 54 | |
| 55 | public function updateChannel(Request $request, string $key, NotificationManager $manager): RedirectResponse |
| 56 | { |
| 57 | abort_unless($manager->has($key), 404); |
| 58 | |
| 59 | $driver = $manager->driver($key); |
| 60 | $schema = $driver->configSchema(); |
| 61 | $enabled = $request->boolean('enabled'); |
| 62 | |
| 63 | $rules = []; |
| 64 | foreach ($schema as $field => $def) { |
| 65 | $rules["config.{$field}"] = $enabled && ($def['required'] ?? false) ? 'required' : 'nullable'; |
| 66 | } |
| 67 | $data = $request->validate($rules); |
| 68 | |
| 69 | settings()->set("notification_channels.{$key}.enabled", $enabled); |
| 70 | settings()->set("notification_channels.{$key}.config", $data['config'] ?? []); |
| 71 | |
| 72 | return redirect()->route('admin.notification-settings.index')->with('success', $driver->label() . ' settings saved.'); |
| 73 | } |
| 74 | |
| 75 | /** One event's channel toggles + templates, saved together. */ |
| 76 | public function updateEvent(Request $request, string $event): RedirectResponse |
| 77 | { |
| 78 | abort_unless(config("notification_events.{$event}") !== null, 404); |
| 79 | |
| 80 | $data = $request->validate([ |
| 81 | 'channels' => 'nullable|array', |
| 82 | 'channels.*' => 'string', |
| 83 | 'subject' => 'required|string|max:200', |
| 84 | 'body' => 'required|string|max:2000', |
| 85 | ]); |
| 86 | |
| 87 | settings()->set("notifications.{$event}.channels", $data['channels'] ?? []); |
| 88 | settings()->set("notifications.{$event}.subject", $data['subject']); |
| 89 | settings()->set("notifications.{$event}.body", $data['body']); |
| 90 | |
| 91 | return redirect()->route('admin.notification-settings.index')->with('success', 'Notification settings saved.'); |
| 92 | } |
| 93 | |
| 94 | /** "Send test" — fires immediately (not queued), so the admin sees the real result right away. */ |
| 95 | public function sendTest(Request $request, string $key, NotificationManager $manager): RedirectResponse |
| 96 | { |
| 97 | abort_unless($manager->has($key), 404); |
| 98 | |
| 99 | $data = $request->validate(['to' => 'required|string|max:255']); |
| 100 | |
| 101 | $result = $manager->send($key, $data['to'], 'Test notification', 'This is a test message from your store\'s Notification Settings.'); |
| 102 | |
| 103 | return back()->with($result['ok'] ? 'success' : 'error', $result['ok'] ? 'Test sent.' : ('Test failed: ' . $result['response'])); |
| 104 | } |
| 105 | } |