Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
use OpenNIT\Core\Database;
/**
* Deckt die Erkennung zu langer Eingaben ab.
*
* Die Anwendung arbeitet mit STRICT_TRANS_TABLES: Ein Wert, der breiter ist als
* seine Spalte, wird abgewiesen statt gekürzt. Das ist eine Frage der Eingabe
* und keine Störung – erkannt wird sie deshalb eigens, damit die Oberfläche
* etwas Brauchbares melden kann statt einer allgemeinen Fehlerseite.
*/
return static function (): void {
/** Baut einen PDOException mit gesetztem errorInfo. */
$pdoFehler = static function (string $sqlState, ?int $treiberCode, string $text): PDOException {
$e = new PDOException($text, 0);
// Der Code ist bei PDO der SQLSTATE, nicht der Treibercode.
$reflex = new ReflectionClass(Exception::class);
$p = $reflex->getProperty('code');
$p->setAccessible(true);
$p->setValue($e, $sqlState);
$e->errorInfo = [$sqlState, $treiberCode, $text];
return $e;
};
// ----------------------------------------------------------------
// Erkennung
// ----------------------------------------------------------------
test('Der Zustand für zu lange Werte wird erkannt', function () use ($pdoFehler) {
assertTrue(Database::isValueTooLongError(
$pdoFehler('22001', 1406, "Data too long for column 'name' at row 1")
));
});
test('Auch der Treibercode allein genügt', function () use ($pdoFehler) {
// Je nach Treiber steht der sprechende Code nur in errorInfo.
assertTrue(Database::isValueTooLongError($pdoFehler('HY000', 1406, 'Data too long')));
assertTrue(Database::isValueTooLongError($pdoFehler('HY000', 1265, 'Data truncated')));
});
test('Die Erkennung greift auch durch eine Umhüllung hindurch', function () use ($pdoFehler) {
// execute() kapselt den PDO-Fehler, damit keine Schema-Details nach
// außen dringen; die Einordnung muss trotzdem möglich bleiben.
$gekapselt = new RuntimeException('Datenbankfehler', 0, $pdoFehler('22001', 1406, 'Data too long'));
assertTrue(Database::isValueTooLongError($gekapselt));
});
// ----------------------------------------------------------------
// Abgrenzung
// ----------------------------------------------------------------
test('Andere Datenbankfehler gelten nicht als zu lange Eingabe', function () use ($pdoFehler) {
// Ein doppelter Schlüssel oder eine fehlende Spalte bleiben Störungen.
assertFalse(Database::isValueTooLongError($pdoFehler('23000', 1062, 'Duplicate entry')));
assertFalse(Database::isValueTooLongError($pdoFehler('42S22', 1054, "Unknown column 'x'")));
assertFalse(Database::isValueTooLongError(new RuntimeException('irgendetwas')));
});
test('Die beiden Einordnungen schließen einander aus', function () use ($pdoFehler) {
$zuLang = $pdoFehler('22001', 1406, 'Data too long');
$doppelt = $pdoFehler('23000', 1062, 'Duplicate entry');
assertTrue(Database::isValueTooLongError($zuLang));
assertFalse(Database::isDuplicateKeyError($zuLang));
assertTrue(Database::isDuplicateKeyError($doppelt));
assertFalse(Database::isValueTooLongError($doppelt));
});
// ----------------------------------------------------------------
// Auswertung im Front Controller
// ----------------------------------------------------------------
test('Der Front Controller wertet die Einordnung aus', function () {
$index = (string)file_get_contents(dirname(__DIR__) . '/public/index.php');
assertTrue(str_contains($index, 'isValueTooLongError'), 'Die Einordnung wird nicht genutzt');
assertTrue(str_contains($index, '422'), 'Der eigene Status fehlt');
});
};