Der Autor bekommt beim Block nach dem letzten Rot (oder Gelb mit eingeschalteter Queue) eine kurze Mail statt Stillstand: was passiert ist, dass nichts zu tun ist, und dass das Ergebnis per Mail kommt. Laeuft ueber notifyAuthor() wie Veroeffentlichung und Ablehnung (API-Regel, Sperrliste, adressbezogene Abmeldung, Bounce-Referenz); Opt-out am Typ "abgelehnt". Neue ConversionSource mail_review fuer den Link ins Konto. BladePhpBlockGuardTest wendet das Compiler-Muster auf alle Views an und faengt inline @php( vor einem spaeteren @endphp ab — fand den eigenen Erklaer-Kommentar im Modal, der nur zufaellig funktionierte. Regel in CLAUDE.md. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
42 lines
1.6 KiB
PHP
42 lines
1.6 KiB
PHP
<?php
|
|
|
|
use Illuminate\Support\Facades\File;
|
|
|
|
/**
|
|
* Blade liest `@php … @endphp` VOR allen anderen Direktiven und Kommentaren
|
|
* mit dem Muster `/(?<!@)@php(.*?)@endphp/s` (BladeCompiler::storePhpBlocks).
|
|
* Ein inline `@php(...)` vor einem späteren Block wird dadurch samt allem
|
|
* dazwischen als ein Rohblock genommen — die Seite kompiliert nicht mehr
|
|
* („unexpected end of file, expecting endif") oder verliert Inhalt. Das
|
|
* gilt auch für `@php(`, das nur in einem Blade-Kommentar steht.
|
|
*
|
|
* Regel: Sobald eine Datei `@endphp` enthält, gibt es darin kein inline
|
|
* `@php(` — immer die Blockform benutzen.
|
|
*/
|
|
test('no view mixes inline @php( with a later @php block', function () {
|
|
$offenders = [];
|
|
|
|
foreach (File::allFiles(resource_path('views')) as $view) {
|
|
if (! str_ends_with($view->getFilename(), '.blade.php')) {
|
|
continue;
|
|
}
|
|
|
|
$contents = File::get($view->getRealPath());
|
|
|
|
if (! str_contains($contents, '@endphp')) {
|
|
continue;
|
|
}
|
|
|
|
// Exakt das Muster des Compilers: jeder Treffer, dessen Inhalt mit
|
|
// `(` beginnt, ist ein inline @php(, das einen Block verschluckt.
|
|
preg_match_all('/(?<!@)@php(.*?)@endphp/s', $contents, $matches, PREG_OFFSET_CAPTURE);
|
|
|
|
foreach ($matches[1] as [$body, $offset]) {
|
|
if (str_starts_with($body, '(')) {
|
|
$offenders[] = sprintf('%s:%d', $view->getRelativePathname(), substr_count($contents, "\n", 0, $offset) + 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
expect($offenders)->toBe([], "Inline @php( vor einem @php-Block — auf Blockform umstellen:\n".implode("\n", $offenders));
|
|
});
|