orderBy('name')->get()->all(); } public function get(string $slug): EmailTemplate { $template = EmailTemplate::query()->where('slug', $slug)->first(); if ($template === null) { throw new RuntimeException("Email template [{$slug}] not found."); } return $template; } public function update(string $slug, string $subject, string $bodyHtml): EmailTemplate { $template = $this->get($slug); $template->update([ 'subject' => $subject, 'body_html' => $bodyHtml, ]); return $template->fresh(); } public function render(string $slug, array $variables): array { $template = $this->get($slug); $defaults = [ 'app_name' => config('app.name'), 'from_email' => config('mail.from.address'), ]; $vars = array_merge($defaults, $variables); return [ 'subject' => $this->replacePlaceholders($template->subject, $vars), 'html' => $this->wrapHtml($this->replacePlaceholders($template->body_html, $vars)), ]; } public function sampleVariables(string $slug): array { $base = [ 'username' => 'preview.user', 'display_name' => 'Preview User', ]; return match ($slug) { 'password_reset' => array_merge($base, [ 'reset_url' => url('/password/reset/preview-token-not-valid'), 'expires_minutes' => '60', ]), 'password_changed' => array_merge($base, [ 'changed_at' => now()->format('Y-m-d H:i:s').' WIB', 'changed_by' => 'admin (preview)', ]), default => $base, }; } private function replacePlaceholders(string $text, array $variables): string { foreach ($variables as $key => $value) { $text = str_replace('{' . $key . '}', (string) $value, $text); } return $text; } private function wrapHtml(string $body): string { return '' . '' . $body . ''; } }