PHPackages                             wapplersystems/inquiry - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. wapplersystems/inquiry

ActiveTypo3-cms-extension[Utility &amp; Helpers](/categories/utility)

wapplersystems/inquiry
======================

The extension is a universal TYPO3 extension that allows visitors to create enquiries for quotes.

101PHP

Since Jan 19Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/WapplerSystems/t3-inquiry)[ Packagist](https://packagist.org/packages/wapplersystems/inquiry)[ RSS](/packages/wapplersystems-inquiry/feed)WikiDiscussions release/v13 Synced today

READMEChangelogDependenciesVersions (3)Used By (0)

TYPO3 Extension `inquiry`
=========================

[](#typo3-extension-inquiry)

Die TYPO3-Extension `inquiry` ist eine universelle und hochflexible Lösung, um Besuchern Ihrer Website das Sammeln von Produkten oder Leistungen in einer Anfrageliste zu ermöglichen. Ähnlich wie bei einem Warenkorb können Nutzer Artikel hinzufügen, verwalten und anschließend ein individuelles Angebot anfordern – oder die Liste als **PDF exportieren** und per **Preload-Link** erneut aufrufen.

[![TYPO3 13](https://camo.githubusercontent.com/736311568ec9205d9514b2264785750e198a4a26243578a9dff7f7bdb84a5d05/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5459504f332d31332d6f72616e67652e7376673f7374796c653d666c61742d737175617265)](https://typo3.org/)[![License](https://camo.githubusercontent.com/37c9aa11511cabae70647d9c92694be2a286bd25c284de636a228b0ecff380ea/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d47504c2d2d322e302d626c75652e7376673f7374796c653d666c61742d737175617265)](https://www.gnu.org/licenses/gpl-2.0.html)

🚀 Vorteile &amp; Funktionen
---------------------------

[](#-vorteile--funktionen)

- **Universell einsetzbar**: Dank eines Adapter-Konzepts kann die Extension mit beliebigen Datensätzen (Produkte, Seiten, News, etc.) arbeiten.
- **Moderne User Experience**:
    - Produkte können ohne Neuladen der Seite per **Ajax** hinzugefügt oder entfernt werden.
    - Dynamische Aktualisierung der Badge-Counter (z. B. im Header).
- **Flexibles Formularwesen**: Nutzt das TYPO3 Form-Framework. Formulare können einfach per Event-Listener erweitert oder angepasst werden.
- **Zwei-Mail-Versand**: Beim Absenden der Anfrageliste erhalten sowohl die konfigurierten Empfänger (`EmailToReceiver`) als auch der Anfragende selbst eine Bestätigungsmail (`EmailToSender`). Beide Mails sind über eigene Events anpassbar.
- **FlyIn-Liste**: Optionaler Bootstrap-Offcanvas, der die aktuelle Anfrageliste (Bild + Titel + Entfernen-Button) als ausfahrbares Panel anzeigt. Per Custom-Event (`inquiry:item-removed`) synchronisiert sich die FlyIn live mit der Anfrageliste-Seite und umgekehrt.
- **Mehrfenster-/Tab-Synchronisation**: Anfrageliste, FlyIn und Toggle-Buttons halten sich automatisch in mehreren geöffneten Tabs und Fenstern desselben Browsers synchron — über `BroadcastChannel` für Echtzeit-Sync und `visibilitychange` als Fallback beim Tab-Fokuswechsel.
- **PDF-Export**: Die Anfrageliste kann inklusive ausgefüllter Felder als PDF heruntergeladen werden.
- **Preload-Link**: Jedes PDF enthält einen eindeutigen Link, mit dem die Liste auf der Website wiederhergestellt und die Felder vorausgefüllt werden können.
- **Einfache Integration**: ViewHelper für Buttons ("In die Anfrageliste") und Links zur Liste werden mitgeliefert.
- **Entwicklerfreundlich**: Umfangreiche PSR-14 Events ermöglichen tiefgreifende Anpassungen im Prozess (z. B. eigene Finisher, Validierungen oder Datenauflösung).
- **Zukunftssicher**: Volle Unterstützung für TYPO3 v13.

🛠 Funktionsweise
----------------

[](#-funktionsweise)

Die Extension verwaltet eine Liste von Identifikatoren (z. B. UIDs). Über einen **Adapter** (Event-Listener) entscheiden Sie, wie diese IDs in reale Objekte aufgelöst werden und welche Informationen im Anfrageformular erscheinen sollen.

Listen-Zustände (Items + Formularfeld-Vorausfüllwerte) werden als **DB-Snapshots** in der Tabelle `tx_inquiry_list_snapshot` gespeichert. Jeder Snapshot erhält einen deterministischen 32-stelligen Bezeichner (MD5 der serialisierten Daten), der als URL-Parameter weitergegeben wird. URL-Parameter zur direkten Datenübertragung werden nicht mehr verwendet.

Ein Beispiel für einen Adapter finden Sie im Verzeichnis der Extension oder als separates Repository.

📥 Installation
--------------

[](#-installation)

Die empfohlene Installation erfolgt über [Composer](https://getcomposer.org/):

```
composer require wapplersystems/inquiry
```

Nach der Installation muss das Datenbankschema aktualisiert werden:

```
vendor/bin/typo3 database:updateschema
```

📋 Einrichtung
-------------

[](#-einrichtung)

1. **TypoScript einbinden**: Fügen Sie das statische TypoScript der Extension zu Ihrem Template hinzu.
2. **Adapter erstellen**: Implementieren Sie Event-Listener für `ResolveItemEvent`, um Ihre Objekte (z. B. Produkte) der Extension bekannt zu machen.
3. **ViewHelper nutzen**: Integrieren Sie die Buttons und die FlyIn in Ihre Fluid-Templates: ```
    {namespace i=WapplerSystems\Inquiry\ViewHelpers}

    ```
4. **Plugins einbinden**: Für PDF-Export und Preload werden zusätzliche Plugins/typeNums benötigt (siehe unten).

🔢 typeNums &amp; Endpunkte
--------------------------

[](#-typenums--endpunkte)

typeNumActionZweck678934`toggleItemStatus`Artikel hinzufügen / entfernen678935`getItems`Aktuelle Liste zurückgeben (`{items}`)678936`removeItem`Artikel entfernen, gibt aktualisierte Items-Liste zurück678937`preloadItems`Snapshot aus DB laden, Session befüllen, Weiterleitung mit Identifier678938`generatePdf`Snapshot aus DB laden, PDF rendern und ausliefern678939`saveListSnapshot`POST-Endpunkt – Items + Prefill speichern, gibt `{identifier}` zurück678940`getPrefill`GET – Prefill-Daten für einen Identifier zurückgeben678941`flyInItems`HTML-Fragment der aktuellen Anfrageliste für die FlyInDie URLs für typeNum 678939, 678940 und 678941 werden automatisch als Meta-Tags in alle Seiten eingefügt:

- `` → URL für typeNum 678939
- `` → URL für typeNum 678940
- `` → URL für typeNum 678941

📄 PDF-Export
------------

[](#-pdf-export)

### Ablauf

[](#ablauf)

1. Nutzer klickt auf `.inquiry-generate-pdf`.
2. JavaScript sammelt alle Eingaben mit `[data-inquiry-pdf-key][data-inquiry-pdf-hash]` als Prefill-Objekt.
3. JavaScript sendet `{items, prefill}` per POST-JSON an `saveListSnapshotAction` (typeNum 678939).
4. Server speichert den Snapshot in der DB und gibt `{identifier}` zurück.
5. JavaScript navigiert zu `?type=678938&tx_inquiry[identifier]=`.
6. `generatePdfAction` lädt den Snapshot, rendert das PDF und liefert es aus.
7. Das PDF enthält einen Preload-Link: `/?type=678937&tx_inquiry[identifier]=`.

### Adapter-Integration

[](#adapter-integration)

Im Adapter-Event-Listener werden die Formularfelder, die im PDF erscheinen sollen, mit `data-inquiry-pdf-key` und `data-inquiry-pdf-hash` ausgezeichnet (z. B. in `buildFormItem()`). `resolveItem()` liest `$event->getPdfFields()` und rendert ein dediziertes PDF-Template (z. B. `Item/ItemPdf.html`), das als `htmlPreviewPdf` am Event gesetzt wird.

🔗 Preload-Link
--------------

[](#-preload-link)

### Ablauf

[](#ablauf-1)

1. Nutzer klickt den Link im PDF.
2. `preloadItemsAction` (typeNum 678937) liest den Identifier, lädt die Items aus dem DB-Snapshot und schreibt sie in die Session.
3. Weiterleitung zur Listenseite mit `?tx_inquiry[identifier]=`.
4. JavaScript erkennt den Identifier in der URL, ruft `getPrefillAction` (typeNum 678940) auf und befüllt die Formularfelder mit den zurückgegebenen Werten.

🗄 Datenbankschema
-----------------

[](#-datenbankschema)

Tabelle `tx_inquiry_list_snapshot`:

SpalteTypBeschreibung`identifier``CHAR(32)` PRIMARY KEYMD5 von `json_encode(['items' => ..., 'prefill' => ...])``items``TEXT` (JSON)Array von `{uid, type, hash}``prefill``TEXT` (JSON)`{hash: {key: value}}` – Feldwerte für das PDF`crdate``INT`ErstellungszeitstempelDer Identifier ist deterministisch: gleiche Items + gleicher Prefill erzeugen immer denselben Hash, sodass doppelte DB-Einträge automatisch vermieden werden.

🏗 Events
--------

[](#-events)

Nutzen Sie die folgenden Events für individuelle Anpassungen:

- `BuildInquiryFormEvent`: Passt die Formular-Definition an.
- `BuildInquiryFormContactEvent`: Ergänzt Kontaktfelder im Formular.
- `BuildInquiryFormItemEvent`: Ergänzt item-spezifische Felder pro Artikel.
- `ResolveItemEvent`: Löst eine UID in ein Objekt auf; setzt `htmlPreview` (Web) und `htmlPreviewPdf` (PDF).
- `CanResolveItemByIdentifierEvent`: Prüft, ob der Adapter für einen gegebenen Typ zuständig ist.
- `CreateEmailToReceiverFinisherEvent`: Ermöglicht die Anpassung der Empfänger-Mail (Vorlage, Betreff, Reply-To etc.).
- `CreateEmailToSenderFinisherEvent`: Ermöglicht die Anpassung der Bestätigungs-Mail an den Anfragenden.
- ... und viele weitere.

📧 E-Mail-Versand
----------------

[](#-e-mail-versand)

Beim Absenden der Anfrageliste werden zwei Mails verschickt:

1. **An die konfigurierten Empfänger** (`EmailToReceiver`): enthält die Kontaktdaten des Anfragenden und die Liste der angefragten Artikel.
2. **An den Anfragenden** (`EmailToSender`): Bestätigungsmail mit derselben Zusammenfassung; das Reply-To ist auf die Standard-Absender-Adresse des Systems gesetzt, damit Antworten an die Empfänger gehen.

Beide Mails verwenden das TYPO3 Form-Framework `EmailFinisher`. Adapter können über die jeweiligen `Create*FinisherEvent`-Events Vorlagen, Layouts, Betreff oder Empfänger überschreiben.

🛒 FlyIn (Offcanvas-Liste)
-------------------------

[](#-flyin-offcanvas-liste)

Die FlyIn ist ein optionaler Bootstrap-Offcanvas, mit dem Nutzer ihre aktuelle Anfrageliste jederzeit aus dem Header heraus einsehen können – inklusive Vorschaubild, Titel und Entfernen-Button pro Artikel sowie eines CTA-Links zur vollständigen Anfrageliste-Seite (`plugin.tx_inquiry.settings.listPageUid`).

### Ablauf

[](#ablauf-2)

1. `` im Header öffnet das Offcanvas (Bootstrap `data-bs-toggle="offcanvas"`).
2. Beim Öffnen lädt `inquiry-flyin.js` per `fetch` ein HTML-Fragment vom `flyInItemsAction` (typeNum 678941) und ersetzt den Inhalt der Offcanvas-Body.
3. Die Standard-Vorlage `Templates/Inquiry/FlyInItems.html` rendert Bild + Titel + Entfernen-Button (Adapter können eine eigene Variante hinterlegen, um z. B. Spec-Lines anzuzeigen).
4. Bei leerer Liste wird ein Empty-State angezeigt und der CTA ausgeblendet.

### Cross-Component-Sync

[](#cross-component-sync)

Beide Entfern-Pfade (Button in der FlyIn, Delete-Button in der Anfrageliste-Seite) feuern nach erfolgreichem Remove-Request ein Custom-Event:

```
document.dispatchEvent(new CustomEvent('inquiry:item-removed', {
    detail: { uid, type }
}));
```

Beide Komponenten lauschen darauf und entfernen das passende DOM-Element optimistisch (clientseitig), ohne erneuten Server-Roundtrip. Lediglich beim Wechsel auf den Empty-State wird der Inhalt der FlyIn frisch geladen.

### Adapter-Integration

[](#adapter-integration-1)

Adapter überschreiben üblicherweise:

- `Templates/Inquiry/FlyInItems.html` für reichere Item-Darstellung (z. B. Spec-Lines).
- `resolveItem()`-Listener: `$event->setResolvedImage(...)` setzen, damit Vorschaubilder erscheinen.

🔄 Mehrfenster-/Tab-Synchronisation
----------------------------------

[](#-mehrfenster-tab-synchronisation)

Der Zustand der Anfrageliste bleibt zwischen mehreren geöffneten Tabs und Fenstern desselben Browsers automatisch konsistent. Drei Schichten greifen ineinander:

1. **Lokale Custom-Events** (`inquiry:item-removed`, `inquiry:items-changed`) — DOM-Reaktionen innerhalb desselben Tabs.
2. **`BroadcastChannel('tx_inquiry:sync')`** — Echtzeit-Sync zwischen Tabs/Fenstern desselben Browsers. Nach erfolgreichem `toggleItemStatus`/`removeItem` sendet der auslösende Tab `{ type: 'items-changed', items }`. Empfänger gleichen Badge, Toggle-Buttons, FlyIn-Inhalt und – auf der Anfrageliste-Seite – die Item-Fieldsets selbst ab.
3. **`visibilitychange`** — Wenn ein Tab den Fokus zurückgewinnt, lädt der Browser die Items-Liste serverseitig neu und stößt den gleichen Reconcile-Pfad an. Fallback für Konstellationen, in denen der andere Tab nicht aktiv lauschen konnte (z. B. nach einem zwischenzeitlich geschlossenen Fenster).

Auf der Anfrageliste-Seite kommt zusätzlich `swapInquiryForm()` zum Einsatz: bei Abweichungen wird die aktuelle Seite via `fetch` geladen, das `` ersetzt und zuvor erfasste Eingabewerte (Kontaktdaten, Per-Item-Nachrichten) anhand des `name`-Attributs wiederhergestellt. Framework-interne Felder (`__trustedProperties` etc.) kommen frisch aus der Antwort, sodass nachfolgende Submits weiterhin valide bleiben.

---

Authors
-------

[](#authors)

- [Sven Wappler](https://github.com/svewap) - [wappler.systems](https://wappler.systems)
- [Ilja Melnicenko](https://github.com/ille216) - [wappler.systems](https://wappler.systems)

###  Health Score

22

—

LowBetter than 21% of packages

Maintenance57

Moderate activity, may be stable

Popularity3

Limited adoption so far

Community12

Small or concentrated contributor base

Maturity16

Early-stage or recently created project

 Bus Factor1

Top contributor holds 97% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

### Community

Maintainers

![](https://www.gravatar.com/avatar/a944bb90af783b13d74049f2d8adcff598f4e7cb0aad9d7040a6af0bb8c23984?d=identicon)[svewap](/maintainers/svewap)

![](https://avatars.githubusercontent.com/u/4037660?v=4)[iljam](/maintainers/iljam)[@iljam](https://github.com/iljam)

---

Top Contributors

[![svewap](https://avatars.githubusercontent.com/u/1734738?v=4)](https://github.com/svewap "svewap (32 commits)")[![ille216](https://avatars.githubusercontent.com/u/35601242?v=4)](https://github.com/ille216 "ille216 (1 commits)")

---

Tags

typo3typo3-cms-extensiontypo3-extension

### Embed Badge

![Health badge](/badges/wapplersystems-inquiry/health.svg)

```
[![Health](https://phpackages.com/badges/wapplersystems-inquiry/health.svg)](https://phpackages.com/packages/wapplersystems-inquiry)
```

###  Alternatives

[hackzilla/ticket-bundle

This Bundle provides multilingual ticketing functionality for Symfony applications.

6529.3k1](/packages/hackzilla-ticket-bundle)[infinityxtech/filament-world-map-widget

World map stats widget

135.9k](/packages/infinityxtech-filament-world-map-widget)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
