112 lines
4.2 KiB
PHP
112 lines
4.2 KiB
PHP
<?php
|
|
|
|
/**
|
|
* Soát toàn bộ template email đang bật trong tbl.template:
|
|
* 1. Mọi {{placeholder}} trong subject/message phải được khai báo ở metadata.variables,
|
|
* nếu không EmailTemplateRenderer sẽ ném InvalidTemplateVariableException lúc gửi.
|
|
* 2. Không còn placeholder kiểu blade {{ $var }} — renderer không hiểu, sẽ in ra nguyên văn.
|
|
* 3. Mọi scenario mà Mailable đang trỏ tới đều phải có row tương ứng.
|
|
*
|
|
* Chạy: php -d zend.assertions=1 tests/check-email-template-placeholders.php
|
|
*/
|
|
|
|
require __DIR__ . '/../vendor/autoload.php';
|
|
|
|
$app = require __DIR__ . '/../bootstrap/app.php';
|
|
$app->make(Illuminate\Contracts\Console\Kernel::class)->bootstrap();
|
|
|
|
$failures = 0;
|
|
|
|
// ── 1 + 2. Từng template phải render được ────────────────────────────────────
|
|
$templates = App\Models\Template::where('status', 1)->get();
|
|
echo "Soát {$templates->count()} template đang bật.\n\n";
|
|
|
|
foreach ($templates as $template) {
|
|
$name = $template->scenario ?: ($template->key ?: "#{$template->id}");
|
|
$content = (string) $template->subject . ' ' . (string) $template->message;
|
|
|
|
preg_match_all('/\{\{\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*\}\}/', $content, $matches);
|
|
$used = array_unique($matches[1]);
|
|
$declared = array_keys($template->variables());
|
|
$undeclared = array_values(array_diff($used, $declared));
|
|
|
|
// Layout dùng {{$content}} làm chỗ cắm nội dung — đó là quy ước riêng, không phải biến.
|
|
$bladeish = $template->scenario === 'layout'
|
|
? []
|
|
: array_values(array_filter(
|
|
preg_match_all('/\{\{\s*\$[a-zA-Z_]+\s*\}\}/', $content, $m2) ? $m2[0] : []
|
|
));
|
|
|
|
if ($undeclared !== []) {
|
|
echo " ✘ {$name}: biến chưa khai báo → " . implode(', ', $undeclared) . "\n";
|
|
$failures++;
|
|
continue;
|
|
}
|
|
|
|
if ($bladeish !== []) {
|
|
echo " ✘ {$name}: còn placeholder blade → " . implode(', ', array_unique($bladeish)) . "\n";
|
|
$failures++;
|
|
continue;
|
|
}
|
|
|
|
echo " ✔ {$name}\n";
|
|
}
|
|
|
|
// ── 3. Mailable nào trỏ tới scenario chưa có row ─────────────────────────────
|
|
echo "\nSoát scenario mà Mailable đang dùng.\n\n";
|
|
|
|
$mailFiles = new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__ . '/../app/Mail'));
|
|
$referenced = [];
|
|
|
|
foreach ($mailFiles as $file) {
|
|
if ($file->isDir() || $file->getExtension() !== 'php') {
|
|
continue;
|
|
}
|
|
if (preg_match_all("/renderFromTemplate\(\s*'([a-z0-9_]+)'/", file_get_contents($file->getPathname()), $m)) {
|
|
foreach ($m[1] as $scenario) {
|
|
$referenced[$scenario] = basename($file->getPathname());
|
|
}
|
|
}
|
|
}
|
|
|
|
$existing = App\Models\Template::where('status', 1)
|
|
->get(['scenario', 'key'])
|
|
->flatMap(fn ($t) => array_filter([$t->scenario, $t->key]))
|
|
->unique()
|
|
->all();
|
|
|
|
foreach ($referenced as $scenario => $mailable) {
|
|
if (in_array($scenario, $existing, true)) {
|
|
echo " ✔ {$scenario} ({$mailable})\n";
|
|
} else {
|
|
echo " ✘ {$scenario} ({$mailable}): KHÔNG có template — gửi sẽ ném ModelNotFoundException\n";
|
|
$failures++;
|
|
}
|
|
}
|
|
|
|
// ── 4. Không còn Mailable nào render qua Blade ───────────────────────────────
|
|
echo "\nSoát Blade trong app/Mail.\n\n";
|
|
|
|
$bladeMailables = [];
|
|
foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator(__DIR__ . '/../app/Mail')) as $file) {
|
|
if ($file->isDir() || $file->getExtension() !== 'php') {
|
|
continue;
|
|
}
|
|
if (preg_match('/\bview:\s*\'|\bmarkdown:\s*\'|->view\(|->markdown\(/', file_get_contents($file->getPathname()))) {
|
|
$bladeMailables[] = basename($file->getPathname());
|
|
}
|
|
}
|
|
|
|
if ($bladeMailables === []) {
|
|
echo " ✔ Không Mailable nào dùng Blade.\n";
|
|
} else {
|
|
echo " ✘ Còn dùng Blade: " . implode(', ', $bladeMailables) . "\n";
|
|
$failures += count($bladeMailables);
|
|
}
|
|
|
|
echo "\n" . ($failures === 0 ? "TẤT CẢ ĐẠT.\n" : "CÓ {$failures} LỖI.\n");
|
|
|
|
assert($failures === 0, "Có {$failures} template/mailable không đạt");
|
|
|
|
exit($failures === 0 ? 0 : 1);
|