Quelltext des aktuellen Standes
<?php
declare(strict_types=1);
/**
* Der Sichtbereich gilt überall gleich – auch in den Zahlen.
*
* Wer nur Tickets bestimmter Standorte sehen darf, bekommt die Liste
* eingeschränkt. Die Zahlen daneben müssen denselben Bereich meinen: Der
* Einstieg in „Mein Bereich", die Zahl am Reiter und die Meldung über neu
* eingegangene Tickets. Weichen sie ab, führt der Einstieg auf eine leere
* Ansicht oder es wird etwas gemeldet, das sich nicht öffnen lässt.
*/
use OpenNIT\Tickets\TicketManager;
return static function (): void {
$wurzel = dirname(__DIR__);
$quelle = static fn (string $pfad): string => (string)file_get_contents($wurzel . '/' . $pfad);
// ----------------------------------------------------------------
// Die Zählung selbst
// ----------------------------------------------------------------
/** Ein Manager, der die abgesetzte Abfrage festhält. */
$manager = static function (array $zeile): array {
$db = new class ($zeile) extends OpenNIT\Core\Database {
public string $sql = '';
/** @var list<mixed> */
public array $params = [];
public function __construct(private array $zeile)
{
}
public function fetchOne(string $sql, array $params = []): ?array
{
$this->sql = $sql;
$this->params = $params;
return $this->zeile;
}
};
$klasse = new ReflectionClass(TicketManager::class);
$tm = $klasse->newInstanceWithoutConstructor();
$feld = $klasse->getProperty('db');
$feld->setAccessible(true);
$feld->setValue($tm, $db);
return [$tm, $db];
};
test('Ohne Einschränkung zählt die Abfrage alles', function () use ($manager) {
[$tm, $db] = $manager(['c' => 3, 'm' => '2026-09-16 10:00:00']);
[$anzahl, $marke] = $tm->countNewSince('2026-09-16 09:00:00', null);
assertSame(3, $anzahl);
assertSame('2026-09-16 10:00:00', $marke);
assertFalse(str_contains($db->sql, 'IN ('), 'Ohne Einschränkung wurde dennoch eingeschränkt');
assertSame(['2026-09-16 09:00:00'], $db->params);
});
test('Mit Einschränkung zählt sie nur die erlaubten Standorte', function () use ($manager) {
[$tm, $db] = $manager(['c' => 1, 'm' => '2026-09-16 10:00:00']);
$tm->countNewSince('2026-09-16 09:00:00', [4, 7]);
assertTrue(str_contains($db->sql, 't.location_id IN (?,?)'), 'Der Sichtbereich fehlt in der Abfrage');
assertSame(['2026-09-16 09:00:00', 4, 7], $db->params);
});
test('Ein leerer Sichtbereich zählt nichts', function () use ($manager) {
// Nicht „alles": Wer keinen Standort sehen darf, sieht keine Tickets.
[$tm, $db] = $manager(['c' => 0, 'm' => null]);
[$anzahl, $marke] = $tm->countNewSince('2026-09-16 09:00:00', []);
assertTrue(str_contains($db->sql, '1=0'), 'Ein leerer Sichtbereich wurde als uneingeschränkt gelesen');
assertSame(0, $anzahl);
assertSame('2026-09-16 09:00:00', $marke, 'Ohne Treffer bleibt die bisherige Marke stehen');
});
test('Zahl und Marke stammen aus einer Abfrage', function () use ($manager) {
// Zwei Abfragen ließen zwischen beiden ein Ticket entstehen, das dann
// zweimal gemeldet würde.
[$tm, $db] = $manager(['c' => 2, 'm' => '2026-09-16 11:30:00']);
$tm->countNewSince('2026-09-16 09:00:00', null);
assertTrue(str_contains($db->sql, 'COUNT(*)'), 'Die Zählung fehlt');
assertTrue(str_contains($db->sql, 'MAX(t.created_at)'), 'Die Marke kommt nicht aus derselben Abfrage');
});
// ----------------------------------------------------------------
// Die Stellen, die zählen
// ----------------------------------------------------------------
test('Jede Zählstelle der Ticketliste kennt den Sichtbereich', function () use ($quelle) {
$ctrl = $quelle('src/Controllers/TicketController.php');
foreach (['public function index(', 'public function apiPoll('] as $stelle) {
$von = strpos($ctrl, $stelle);
assertTrue($von !== false, 'Die Stelle ' . $stelle . ' fehlt');
$rumpf = substr($ctrl, $von, 4000);
assertTrue(
str_contains($rumpf, "\$this->accessibleLocations('view_tickets')"),
$stelle . ' ermittelt den Sichtbereich nicht'
);
assertFalse(
(bool)preg_match('/getMineCount\(\$userId\)/', $rumpf),
$stelle . ' zählt „Mein Bereich" ohne Sichtbereich'
);
}
});
test('Die Meldung über neue Tickets zählt nicht an der Liste vorbei', function () use ($quelle) {
$ctrl = $quelle('src/Controllers/TicketController.php');
$von = strpos($ctrl, 'public function apiPoll(');
$rumpf = substr($ctrl, (int)$von, 4000);
assertTrue(
str_contains($rumpf, '$this->tickets->countNewSince('),
'Die Zählung läuft nicht über die gemeinsame Stelle'
);
assertFalse(
str_contains($rumpf, 'FROM tickets WHERE created_at > ?'),
'Die Zählung geht wieder eigene Wege an der Berechtigung vorbei'
);
});
};