141 lines
4.6 KiB
PHP
141 lines
4.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Http\Controllers\PublicSite;
|
|
|
|
use App\Domain\Contact\MarketingOrigin;
|
|
use App\Http\Controllers\Controller;
|
|
use App\Http\Requests\PublicSite\ContactBriefingRequest;
|
|
use App\Mail\ContactBriefing;
|
|
use App\Mail\ContactBriefingConfirmation;
|
|
use App\Models\SiteSetting;
|
|
use Illuminate\Http\RedirectResponse;
|
|
use Illuminate\Support\Facades\Log;
|
|
use Illuminate\Support\Facades\Mail;
|
|
use Throwable;
|
|
|
|
final class ContactController extends Controller
|
|
{
|
|
private const string DUPLICATE_SESSION_KEY = 'contact_briefing_hash';
|
|
|
|
public function store(ContactBriefingRequest $request): RedirectResponse
|
|
{
|
|
if (filled($request->input('empresa'))) {
|
|
return $this->success();
|
|
}
|
|
|
|
$validated = $request->validated();
|
|
unset($validated['privacidade']);
|
|
|
|
if ($this->isDuplicate($validated)) {
|
|
return $this->success();
|
|
}
|
|
|
|
$this->rememberSubmission($validated);
|
|
|
|
$settings = SiteSetting::instance();
|
|
$fields = $this->buildFields($validated, $this->resolveMarketingOrigin($request));
|
|
|
|
$this->dispatchEmails($settings, $validated['nome'], $validated['email'], $fields);
|
|
|
|
return $this->success();
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $validated
|
|
*/
|
|
private function buildFields(array $validated, ?string $marketingOrigin): array
|
|
{
|
|
return [
|
|
'Nome' => (string) $validated['nome'],
|
|
'E-mail' => (string) $validated['email'],
|
|
'Telefone/WhatsApp' => (string) $validated['telefone'],
|
|
'Tipo de evento' => (string) $validated['tipo_evento'],
|
|
'Data ou período desejado' => isset($validated['data_periodo']) ? (string) $validated['data_periodo'] : null,
|
|
'Cidade' => (string) $validated['cidade'],
|
|
'Número estimado de convidados' => isset($validated['convidados']) ? (string) $validated['convidados'] : null,
|
|
'Serviço de interesse' => isset($validated['servico_interesse']) ? (string) $validated['servico_interesse'] : null,
|
|
'Mensagem' => (string) $validated['mensagem'],
|
|
'Origem de marketing' => $marketingOrigin,
|
|
];
|
|
}
|
|
|
|
/**
|
|
* Reads the origin captured on arrival (SPEC.md WEB-05) so it can
|
|
* ride along with the internal briefing e-mail only — never the
|
|
* confirmation sent to the visitor. Fail-open: any problem reading
|
|
* or interpreting the session value must never block the
|
|
* submission, so it degrades to "not captured" instead.
|
|
*/
|
|
private function resolveMarketingOrigin(ContactBriefingRequest $request): ?string
|
|
{
|
|
try {
|
|
$origin = $request->session()->get(MarketingOrigin::SESSION_KEY, []);
|
|
|
|
return is_array($origin) ? MarketingOrigin::describe($origin) : null;
|
|
} catch (Throwable $exception) {
|
|
Log::warning('Falha ao ler origem de marketing armazenada (ignorada; fail-open)', [
|
|
'exception' => $exception::class,
|
|
]);
|
|
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $validated
|
|
*/
|
|
private function isDuplicate(array $validated): bool
|
|
{
|
|
$hash = $this->hash($validated);
|
|
|
|
return session()->get(self::DUPLICATE_SESSION_KEY) === $hash;
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $validated
|
|
*/
|
|
private function rememberSubmission(array $validated): void
|
|
{
|
|
session()->put(self::DUPLICATE_SESSION_KEY, $this->hash($validated));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $validated
|
|
*/
|
|
private function hash(array $validated): string
|
|
{
|
|
return hash('sha256', serialize($validated));
|
|
}
|
|
|
|
/**
|
|
* @param array<string, mixed> $fields
|
|
*/
|
|
private function dispatchEmails(SiteSetting $settings, string $name, string $email, array $fields): void
|
|
{
|
|
$attempt = function () use ($settings, $name, $email, $fields): void {
|
|
if (filled($settings->email)) {
|
|
Mail::to($settings->email)->send(new ContactBriefing($fields));
|
|
}
|
|
|
|
if (filled(config('mail.default'))) {
|
|
Mail::to($email)->send(new ContactBriefingConfirmation($name, (string) $settings->brand_name));
|
|
}
|
|
};
|
|
|
|
try {
|
|
$attempt();
|
|
} catch (Throwable $exception) {
|
|
Log::error('Falha ao enviar briefing de contato', [
|
|
'exception' => $exception,
|
|
]);
|
|
}
|
|
}
|
|
|
|
private function success(): RedirectResponse
|
|
{
|
|
return redirect()->route('briefing')->with('status', 'briefing-sent');
|
|
}
|
|
}
|