''", [], 0 ); } /** Das jüngste Änderungsdatum im Bestand – der Stand der Daten. */ public static function juengsterStand(): ?string { $wert = Database::fetchValue('SELECT MAX(stand) FROM bankinstitute'); return is_string($wert) && $wert !== '' ? $wert : null; } /** * Der Eintrag zu einer Bankleitzahl. * * Steht die Bankleitzahl mehrfach in der Datei – bei den Großbanken einmal * je Filiale –, gewinnt ein Eintrag mit Zugangspunkt vor einem ohne; unter * gleichen entscheidet die Reihenfolge der Datei. Die Zugangspunkte * derselben Bankleitzahl sind identisch, verschieden ist nur der Ort. * * @return array|null */ public static function findeNachBlz(string $blz): ?array { $blz = self::nurZiffern($blz); if ($blz === '') { return null; } $zeile = Database::fetchOne( "SELECT * FROM bankinstitute WHERE blz = ? ORDER BY (pintan_url <> '') DESC, nr LIMIT 1", [$blz] ); return $zeile === false ? null : $zeile; } /** * Suche über Bankleitzahl, BIC, Name und Ort. * * Gesucht wird immer in allen vier Feldern, und zwar in einem Zug: Wer * „1822“ eingibt, meint mal die Bankleitzahl und mal die 1822direkt – eine * Eingabe nur deshalb als Bankleitzahl zu lesen, weil sie aus Ziffern * besteht, verschwiege ihm die Bank, die er sucht. * * Verglichen wird die Bankleitzahl von vorn („5005“ findet 50050201 und * 50050222), alles Übrige als Wortbestandteil. Treffer in der * Bankleitzahl stehen oben, dann die mit Zugangspunkt. * * @return list> */ public static function suche(string $begriff, int $grenze = self::TREFFER_GRENZE): array { $begriff = trim($begriff); if ($begriff === '') { return []; } $grenze = max(1, min($grenze, self::TREFFER_GRENZE)); $muster = self::maskiere($begriff); // Eine Bankleitzahl steht in der Tabelle ohne Leerzeichen; die Eingabe // darf welche enthalten. Bei einer Eingabe ohne Ziffern bleibt nichts // übrig – dann trifft der Vergleich schlicht nie. $blz = self::nurZiffern($begriff); $blzMuster = $blz === '' ? null : self::maskiere($blz) . '%'; $text = '%' . $muster . '%'; return Database::fetchAll( "SELECT * FROM bankinstitute WHERE (? IS NOT NULL AND blz LIKE ? ESCAPE '!') OR institut LIKE ? ESCAPE '!' OR ort LIKE ? ESCAPE '!' OR bic LIKE ? ESCAPE '!' ORDER BY (? IS NOT NULL AND blz LIKE ? ESCAPE '!') DESC, (pintan_url <> '') DESC, blz, institut, ort LIMIT " . $grenze, [ $blzMuster, (string)$blzMuster, $text, $text, $text, $blzMuster, (string)$blzMuster, ] ); } /** * Ersetzt den gesamten Bestand. * * In einer Transaktion und satzweise über eine mehrzeilige INSERT-Anweisung: * Die Datei bringt knapp viertausend Zeilen mit, und viertausend einzelne * Anweisungen dauern spürbar länger als vierzig. * * @param list> $saetze * @return int Zahl der geschriebenen Zeilen */ public static function ersetze(array $saetze): int { $spalten = [ 'nr', 'blz', 'bic', 'institut', 'ort', 'rechenzentrum', 'organisation', 'hbci_adresse', 'hbci_version', 'pintan_url', 'pintan_version', 'stand', ]; return (int)Database::transaktion(static function () use ($saetze, $spalten): int { Database::execute('DELETE FROM bankinstitute'); $geschrieben = 0; foreach (array_chunk($saetze, 100) as $block) { $werte = []; $platz = []; foreach ($block as $satz) { foreach ($spalten as $spalte) { $werte[] = $satz[$spalte] ?? null; } $platz[] = '(' . implode(',', array_fill(0, count($spalten), '?')) . ')'; } Database::execute( 'INSERT INTO bankinstitute (' . implode(', ', $spalten) . ') VALUES ' . implode(', ', $platz), $werte ); $geschrieben += count($block); } return $geschrieben; }); } public static function leeren(): void { Database::execute('DELETE FROM bankinstitute'); } /** Bankleitzahlen stehen in der Datei mit führenden Nullen – nur Ziffern zählen. */ public static function nurZiffern(string $wert): string { return preg_replace('/\D/', '', $wert) ?? ''; } /** Maskiert die LIKE-Platzhalter einer Sucheingabe. */ private static function maskiere(string $begriff): string { return str_replace(['!', '%', '_'], ['!!', '!%', '!_'], $begriff); } }