66 lines
2.5 KiB
PHP
66 lines
2.5 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Email;
|
|
|
|
use App\Models\Template;
|
|
use App\Support\EmailScenarioRegistry;
|
|
use Illuminate\Http\Exceptions\HttpResponseException;
|
|
|
|
final class TemplateGuard
|
|
{
|
|
public function assertCanSave(Template $template): void
|
|
{
|
|
if ($template->exists) {
|
|
$this->assertKeepsRegisteredIdentity($template);
|
|
}
|
|
|
|
$definition = EmailScenarioRegistry::describe($template->key, $template->scenario);
|
|
if (!$definition['registered']) {
|
|
return;
|
|
}
|
|
|
|
$duplicate = Template::query()
|
|
->whereKeyNot($template->id)
|
|
->where(fn ($q) => $q->where('key', $definition['scenario'])->orWhere('scenario', $definition['scenario']))
|
|
->exists();
|
|
if ($duplicate) {
|
|
$this->reject("Scenario \"{$definition['scenario']}\" đã có template, không tạo thêm được.");
|
|
}
|
|
|
|
if (!$definition['permissions']['disable'] && (int) $template->status !== 1) {
|
|
$this->reject('Template hệ thống này không được tắt: code đang gửi email theo template này.');
|
|
}
|
|
|
|
$missing = EmailScenarioRegistry::missingVariables($definition['required_variables'], $template->subject, $template->message);
|
|
if ($missing !== []) {
|
|
$this->reject(
|
|
'Template thiếu biến bắt buộc: ' . implode(', ', array_map(fn ($key) => '{{$' . $key . '}}', $missing)),
|
|
['missing_variables' => $missing],
|
|
);
|
|
}
|
|
}
|
|
|
|
public function assertCanDelete(Template $template): void
|
|
{
|
|
$definition = EmailScenarioRegistry::describe($template->key, $template->scenario);
|
|
|
|
if (!$definition['permissions']['delete']) {
|
|
$this->reject('Template hệ thống không được xoá: code đang gửi email theo template này.');
|
|
}
|
|
}
|
|
|
|
private function assertKeepsRegisteredIdentity(Template $template): void
|
|
{
|
|
$before = EmailScenarioRegistry::describe($template->getOriginal('key'), $template->getOriginal('scenario'));
|
|
|
|
if ($before['registered'] && !$before['permissions']['change_key'] && $template->isDirty(['key', 'scenario'])) {
|
|
$this->reject("Không được đổi key/scenario của template hệ thống \"{$before['scenario']}\".");
|
|
}
|
|
}
|
|
|
|
private function reject(string $message, array $extra = []): never
|
|
{
|
|
throw new HttpResponseException(response()->json(['error' => true, 'message' => $message, ...$extra], 422));
|
|
}
|
|
}
|