Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
/**
* Prueft die Reihenfolge der Argumente an jedem Aufruf des Protokolls.
*
* `log()` nimmt die Einzelheiten vor dem Ergebnis und die Vorher/Nachher-Werte
* ganz am Ende. Wer die Vorher/Nachher-Werte an die Stelle der Einzelheiten
* setzt, schiebt ein Array in den Parameter `$result` – das ist ein Typfehler,
* der erst beim Ausfuehren auffaellt, also erst wenn jemand die Schaltflaeche
* drueckt. Ein solcher Aufruf legt die ganze Aktion lahm, obwohl an ihr selbst
* nichts falsch ist.
*/
return static function (): void {
$wurzel = dirname(__DIR__);
/**
* Zerlegt einen Aufruf in seine Argumente auf oberster Klammerebene.
*
* @param list<array{0:int,1:string,2:int}|string> $tok Token ab der oeffnenden Klammer.
* @param int $von Index der oeffnenden Klammer.
* @return list<string> Argumente als Quelltext.
*/
$argumente = static function (array $tok, int $von): array {
$tiefe = 0; $args = []; $cur = '';
for ($p = $von, $n = count($tok); $p < $n; $p++) {
$t = $tok[$p];
$txt = is_array($t) ? $t[1] : $t;
if ($txt === '(' || $txt === '[') {
$tiefe++;
if ($tiefe === 1 && $txt === '(') { continue; }
} elseif ($txt === ')' || $txt === ']') {
$tiefe--;
if ($tiefe === 0) { $args[] = trim($cur); break; }
}
if ($tiefe === 1 && $txt === ',') { $args[] = trim($cur); $cur = ''; continue; }
if (is_array($t) && $t[0] === T_COMMENT) { continue; }
$cur .= $txt;
}
return $args;
};
/**
* Sammelt alle Protokoll-Aufrufe im Quelltext.
*
* @return list<array{datei:string,zeile:int,name:string,args:list<string>}>
*/
$aufrufe = static function (string $wurzel) use ($argumente): array {
$gefunden = [];
$it = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($wurzel . '/src'));
foreach ($it as $f) {
if (!$f->isFile() || $f->getExtension() !== 'php') { continue; }
$src = (string)file_get_contents($f->getPathname());
$tok = token_get_all($src);
for ($i = 0, $n = count($tok); $i < $n; $i++) {
if (!is_array($tok[$i]) || $tok[$i][0] !== T_STRING) { continue; }
if (!in_array($tok[$i][1], ['log', 'logWithUser'], true)) { continue; }
$j = $i - 1;
while ($j >= 0 && is_array($tok[$j]) && $tok[$j][0] === T_WHITESPACE) { $j--; }
if (!(is_array($tok[$j]) && $tok[$j][0] === T_OBJECT_OPERATOR)) { continue; }
$k = $i + 1;
while ($k < $n && is_array($tok[$k]) && $tok[$k][0] === T_WHITESPACE) { $k++; }
if (($tok[$k] ?? null) !== '(') { continue; }
$gefunden[] = [
'datei' => str_replace($wurzel . '/', '', $f->getPathname()),
'zeile' => $tok[$i][2],
'name' => $tok[$i][1],
'args' => $argumente($tok, $k),
];
}
}
return $gefunden;
};
$alle = $aufrufe($wurzel);
test('Es gibt ueberhaupt Protokoll-Aufrufe zu pruefen', function () use ($alle) {
// Sonst prueft der Rest stillschweigend nichts.
assertTrue(count($alle) > 100, 'Zu wenige Aufrufe gefunden – das Suchmuster passt nicht mehr');
});
test('Das Ergebnis steht als Wort da, nicht als Array', function () use ($alle) {
foreach ($alle as $a) {
// logWithUser fuehrt die Person vorn, alles andere rutscht um eins.
$idx = 6 + ($a['name'] === 'logWithUser' ? 1 : 0);
if (!isset($a['args'][$idx])) { continue; } // kuerzerer Aufruf nutzt den Standard
$r = $a['args'][$idx];
assertFalse(
(bool)preg_match('/^\[|^array\(|^null$/i', $r),
"Argumente verrutscht in {$a['datei']}:{$a['zeile']} – \$result ist {$r}"
);
}
});
test('Die Risikostufe steht als Wort da', function () use ($alle) {
// Rutscht $result, rutscht auch die Stufe – dieselbe Ursache, zweiter Beleg.
$stufen = ['low', 'medium', 'high', 'critical'];
foreach ($alle as $a) {
$idx = 7 + ($a['name'] === 'logWithUser' ? 1 : 0);
if (!isset($a['args'][$idx])) { continue; }
$s = trim($a['args'][$idx], "'\"");
// Variablen und Ausdruecke lassen sich hier nicht beurteilen.
if (!preg_match("/^'[a-z]+'$/", $a['args'][$idx])) { continue; }
assertTrue(
in_array($s, $stufen, true),
"Argumente verrutscht in {$a['datei']}:{$a['zeile']} – Risikostufe ist '{$s}'"
);
}
});
test('Das Ergebnis ist eines der bekannten Worte', function () use ($alle) {
$ergebnisse = ['success', 'failure', 'denied', 'error', 'warning', 'partial'];
foreach ($alle as $a) {
$idx = 6 + ($a['name'] === 'logWithUser' ? 1 : 0);
if (!isset($a['args'][$idx])) { continue; }
if (!preg_match("/^'[a-z_]+'$/", $a['args'][$idx])) { continue; }
$r = trim($a['args'][$idx], "'");
assertTrue(
in_array($r, $ergebnisse, true),
"Unbekanntes Ergebnis in {$a['datei']}:{$a['zeile']} – '{$r}'"
);
}
});
};