Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
use OpenNIT\Core\SchemaInspector;
/**
* Deckt die Kapazität der Wertspalte für Benutzereinstellungen ab.
*
* Mehrere Einstellungen liegen als ein einziger JSON-Wert in
* `user_settings.setting_value` und wachsen mit der Nutzung: gespeicherte
* Filter-Ansichten des Inventars, Dashboard-Belegung, Schnellzugriff, eigene
* Themen-Sortierung, benutzerdefiniertes Menü-Layout. Da die Anwendung mit
* STRICT_TRANS_TABLES arbeitet, weist die Datenbank einen zu langen Wert ab,
* statt ihn zu kürzen. Die Spalte muss deshalb mindestens so viel fassen, wie
* die Anwendung selbst durchlässt.
*/
return static function (): void {
/** Kapazität der Spalte, wie sie sich aus den Migrationen ergibt. */
$kapazitaet = static function (): ?int {
$klasse = new ReflectionClass(SchemaInspector::class);
$inspektor = $klasse->newInstanceWithoutConstructor();
$feld = $klasse->getProperty('migrationsDir');
$feld->setAccessible(true);
$feld->setValue($inspektor, dirname(__DIR__) . '/database/migrations');
$spalten = $inspektor->expectedSchema()['wide_columns'];
return $spalten['user_settings.setting_value']['cap'] ?? null;
};
// ----------------------------------------------------------------
// Deklarierte Kapazität
// ----------------------------------------------------------------
test('Die Wertspalte fasst mindestens TEXT', function () use ($kapazitaet) {
// Nur Spalten ab TEXT werden vom Schema-Abgleich überwacht; darunter
// fiele die Spalte aus der Drift-Erkennung heraus.
$cap = $kapazitaet();
assertTrue($cap !== null, 'Die Spalte ist nicht als breite Spalte deklariert');
assertTrue($cap >= 65535, 'Deklarierte Kapazität: ' . var_export($cap, true));
});
// ----------------------------------------------------------------
// Was die Anwendung durchlässt
// ----------------------------------------------------------------
test('Die zulässige Höchstzahl gespeicherter Ansichten passt hinein', function () use ($kapazitaet) {
// Obergrenzen aus AssetController::savedViewSave(): 20 Ansichten,
// je 60 Zeichen Name und 500 Zeichen Filter. Mehrbyte-Zeichen zählen
// dort nach Zeichen, in der Spalte nach Bytes – deshalb der Aufschlag.
$views = [];
for ($i = 0; $i < 20; $i++) {
$views[] = [
'name' => str_repeat('ä', 60),
'query' => str_repeat('ä', 500),
];
}
assertTrue(strlen(json_encode($views)) <= $kapazitaet(), 'Die Höchstbelegung passt nicht in die Spalte');
});
test('Das größte zulässige Menü-Layout passt hinein', function () use ($kapazitaet) {
// ApiController::normalizeNavLayout() weist alles über 8192 Zeichen ab;
// bis dahin muss die Spalte den Wert aufnehmen können.
assertTrue(8192 <= $kapazitaet(), 'Ein zulässiges Menü-Layout passt nicht in die Spalte');
});
// ----------------------------------------------------------------
// Grund für die Verbreiterung
// ----------------------------------------------------------------
test('Die frühere Breite hätte für wenige Ansichten gereicht', function () {
// Begründet die Migration: Die Filterleiste sendet alle acht Felder mit,
// auch die leeren – der Filter ist deshalb unabhängig vom tatsächlich
// Gefilterten rund 80 Zeichen lang und das JSON war nach vier Ansichten
// an der alten Grenze von 500 Zeichen.
$query = 'q=&category=3&manufacturer=&type=&location=12&status=active&assignment=&warranty=';
$views = [];
for ($i = 0; $i < 4; $i++) {
$views[] = ['name' => 'Ansicht ' . ($i + 1), 'query' => $query];
}
assertTrue(strlen(json_encode($views)) <= 500, 'Vier Ansichten passten schon vorher nicht');
$views[] = ['name' => 'Ansicht 5', 'query' => $query];
assertTrue(strlen(json_encode($views)) > 500, 'Die fünfte Ansicht hätte auch vorher gepasst');
});
};