# Globale Suche erweitern

Letzte Aktualisierung: 2026-02-21

Diese Doku erklärt, wie neue Entitäten sauber in die globale Suche integriert werden.

## Überblick

Es gibt zwei Suchausgaben mit derselben Datenquelle:

1. **Aside-Preview** (`admin/search/data`)
   - zeigt je Resource Count + bis zu 5 Preview-Einträge.
2. **Vollseite Suche** (`search/data` -> `/search`)
   - zeigt gemischte Trefferliste über alle Resources.

Die zentrale Fassade liegt in:

- `/lib/Support/SearchConfig.php`

Die eigentliche Logik ist in Provider aufgeteilt:

- `/lib/Support/Search/SearchSqlResourceProvider.php`
- `/lib/Support/Search/SearchUiMetaProvider.php`
- `/lib/Support/Search/SearchItemMapperProvider.php`
- `/lib/Support/Search/SearchSpecialResourceProvider.php`
- `/lib/Support/Search/SearchQueryNormalizer.php`

## Relevante Dateien

- `/lib/Support/SearchConfig.php`
  - stabile Orchestrierungs-Fassade (kompatible Methoden nach außen)
- `/lib/Support/Search/SearchSqlResourceProvider.php`
  - Resource-Definitionen (SQL + Permission + Label) + Tenant-Filter
- `/lib/Support/Search/SearchUiMetaProvider.php`
  - URL- und Icon-Mapping pro Resource-Key
- `/lib/Support/Search/SearchItemMapperProvider.php`
  - Mapping SQL-Row -> Preview-/Result-Item
- `/lib/Support/Search/SearchSpecialResourceProvider.php`
  - Spezialressourcen (`docs`, `hotkeys`)
- `/lib/Support/Search/SearchQueryNormalizer.php`
  - Query-Normalisierung für LIKE/Score
- `/pages/admin/search/data().php`
  - Aside-Preview API (Counts + Preview)
- `/pages/search/data().php`
  - Volltext-Treffer API
- `/templates/partials/app-main-aside.phtml`
  - Sichtbarer Eintrag im Such-Panel (`data-search-key=...`)
- `/web/js/components/app-global-search.js`
  - Render-Logik (generisch; meist keine Anpassung nötig)
- `/lib/Service/Docs/DocsCatalogService.php`
  - Zentrale Katalog-/Anchor-Logik für Entwicklerdoku (Single Source of Truth)

## Standard-Vorgehen für neue Resource

### 1) Resource in `SearchSqlResourceProvider::resources()` anlegen

Neue Struktur mit:

- `key` (z. B. `scheduled-jobs`)
- `label` (übersetzbar via `t(...)`)
- `permission` (z. B. `PermissionService::JOBS_VIEW`)
- `countSql` + `countParams`
- `previewSql` + `previewParams`
- `resultSql` + `resultParams`

Regeln:

- SQL immer mit `... like ? escape '\\'`.
- Bei tenant-sensitiven Entitäten `{{tenantFilter}}` nutzen und in `SearchSqlResourceProvider::tenantScopeFilters()` ergänzen.
- Preview-Query immer mit `limit ?`.

### 2) URL-/Icon-/Mapping ergänzen

- `SearchUiMetaProvider::iconForKey()` erweitern
- `SearchUiMetaProvider::listUrl()` erweitern
- `SearchItemMapperProvider::mapPreviewItem()` ergänzen (falls Spezialformat nötig)
- `SearchItemMapperProvider::mapResultItem()` ergänzen (falls Spezialformat nötig)

Ziel:

- Preview und Volltreffer sollen sprechende Labels zeigen.
- URLs sollen direkt auf sinnvolle Zielseiten gehen.

### 3) Eintrag im Aside-Search-Panel anlegen

In `/templates/partials/app-main-aside.phtml`:

- `<li data-search-key="..." data-search-base="...">` ergänzen
- Anzeige per Permission guarden (z. B. `$canViewJobs`)

Wichtig:

- `data-search-key` muss exakt dem `key` in `SearchConfig` entsprechen.

### 4) i18n prüfen

Neue Labels in:

- `/i18n/default_de.json`
- `/i18n/default_en.json`

## Sicherheits- und Qualitätsregeln

- Permission in `SearchConfig` setzen, nicht nur im Aside.
- Tenant-Scope für tenant-bezogene Daten nicht vergessen.
- Keine sensiblen Daten im Preview-Label.
- Bei optionalen Modulen nur dann Resource aktivieren, wenn Schema vorhanden ist (oder Migration als Pflicht voraussetzen).

## Kurzes Beispiel: `scheduled-jobs`

Integration umfasst:

- Resource in `SearchSqlResourceProvider::resources()`
- Mapping auf `admin/scheduled-jobs/edit/{id}`
- Icon `bi-calendar-check`
- Aside-Search-Item mit `data-search-key="scheduled-jobs"`
- Permission `jobs.view`

## Doku-Resource (`docs`) im System

Die Entwicklerdoku ist als eigene Search-Resource integriert:

- Key: `docs`
- Permission: `docs.view`
- Quelle: `docs/*.md` (über `DocsCatalogService`, kein `openapi.yaml`)
- Aside: eigener Block `Documentation` mit Count + Preview
- Vollsuche: Treffer vom Typ `Documentation`
- Ziel-URLs: `admin/docs/{slug}#anchor` (direkter Abschnitt)

Wichtig:

- Anchor-Ermittlung für Docs-Seite und Suche läuft über denselben Service.
- Dadurch bleiben Hash-Links stabil und konsistent.

## Checkliste vor Merge

1. `php -l /lib/Support/SearchConfig.php`
2. `php -l /lib/Support/Search/*.php`
3. `php -l /templates/partials/app-main-aside.phtml`
3. Global Search manuell testen:
   - Sidebar-Suche zeigt Count + Preview
   - Klick auf Resource öffnet richtige Liste
   - `/search?search=...` zeigt Volltreffer
4. Permission-Test:
   - ohne Permission kein Eintrag/keine Treffer
5. Tenant-Scope-Test (falls relevant)
6. Bei `docs` zusätzlich:
   - Preview-Link springt auf richtigen Abschnitt
   - Vollsuche zeigt `Documentation`-Treffer mit sinnvollem Snippet
