glueful / thallo-importers
Thallo content format importers (CSV / Markdown / WordPress) as a removable capability pack.
Requires
- php: ^8.3
- glueful/aegis: ^1.14.0
- glueful/framework: ^1.64.0
- glueful/import-export: ^1.1.1
- glueful/thallo-contracts: v1.0.0-beta.22
- glueful/users: ^2.3.0
- league/commonmark: ^2.8
- symfony/html-sanitizer: ^7.0 || ^8.0
Requires (Dev)
None
Suggests
None
Provides
None
Conflicts
None
Replaces
None
This package is auto-updated.
Last update: 2026-09-12 23:39:11 UTC
README
Content format importers for Thallo — CSV, Markdown/MDX, and
WordPress (WXR) ingestion, plus CSV user provisioning — packaged as a removable capability
pack. It writes all content through Thallo's public ContentWriter contract and never reaches
into the application; install it, disable it, or composer remove it without touching the core.
It is the reference pack of the composable-core
architecture: a real glueful-extension that depends only on glueful/thallo-contracts (+ the
framework and glueful/import-export), declares a capability, and contributes a capability-gated
admin surface.
What it provides
Four import adapters, registered with the import_export.importer container tag and discovered by
the glueful/import-export engine:
| Adapter key | Label | What it ingests |
|---|---|---|
csv.content |
CSV | One content entry per CSV row; fields ↔ columns. |
markdown.content |
Markdown / MDX | YAML front matter → fields; body → a chosen text field (raw vs HTML by the field's format). |
wordpress.content |
WordPress (WXR) | Posts/pages from a WXR export; title/excerpt/slug/date/status/author + content. |
csv.users |
Users (CSV) | Bulk user provisioning (profile + roles) via glueful/users + glueful/aegis. |
The content adapters resolve the target content type and its schema through ContentTypeReader,
map and coerce each row, then write via ContentWriter (validate() for dry-run previews,
createDraft() + optional publish() on commit). Validation failures surface as the contract
ValidationFailed exception — so the pack carries no reference to the engine. Mappings and
body_field are validated against the target schema at plan time, so a typo'd field fails
fast instead of silently importing entries with missing data.
Imported files are treated as untrusted. Markdown bodies are rendered with raw HTML stripped
and unsafe link schemes dropped; WordPress HTML bodies are run through symfony/html-sanitizer
(safe elements only — scripts, iframes, event handlers, and javascript: URLs are removed) before
being stored. User provisioning note: imported accounts are stamped email-verified (bulk
provisioning by an admin who vouches for the addresses) — don't import unvetted address lists.
The capability
The provider registers a single capability in boot():
new Capability('thallo.importers', label: 'Content importers', description: '…');
- Enabled by default. Disable it by setting
'thallo.importers' => falseinconfig/thallo.php'scapabilitiesswitchboard. - Backend-gated, not just UI. Every adapter calls
assertImportersEnabled()(theRequiresImportersCapabilitytrait) as the first line of its plan step — so a directPOST /import-export/importsfor a Thallo adapter fails closed when the capability is disabled, not only the admin controls. - UI-gated. The admin's format-import controls (Settings → Import / Export) and the users
bulk-CSV-import are shown only when
thallo.importersis enabled (via the admin capabilities store).
Boundary
This package depends on glueful/thallo-contracts, glueful/framework, glueful/import-export,
glueful/users, glueful/aegis, and league/commonmark — and never on glueful/thallo (the
application). The repo's composer boundaries check enforces this at both the Composer-dependency
and the source level (no App\ references in src/).
Install
The pack is bundled by default in the Thallo create-project template, so a fresh app has it already. To add it to an existing app (it lives as a path package in this monorepo):
composer require glueful/thallo-importers./thallo extensions:enable thallo-importers(writes the provider into theconfig/extensions.phpallow-list and recompiles the extension cache)
Remove
./thallo extensions:disable thallo-importers, then composer remove glueful/thallo-importers. After
removal:
- The headless CMS core boots; content delivery and the admin work unchanged.
- Snapshot export/import still works — the full-database NDJSON snapshot engine
(
ContentExporter/ContentImporter), its/v1/admin/import-export/upload|downloadendpoints, and the snapshot UI are core-owned, not part of this pack. - The
thallo.importerscapability disappears fromGET /v1/admin/capabilities, so the format-import admin section and the users bulk-CSV import hide automatically.
Not included (deliberately)
Snapshot/backup restore (raw NDJSON of Thallo's own tables, versions, routes, publications, and
blob manifest) stays in core — it necessarily understands Thallo's internal storage model, so it is
not "import through the public content API" and is not exposed through thallo-contracts.