Appearance
Architecture & CLI
For developers
Namespace Kommandhub\DemoData\ → src/. Plugin class KmhDemoDataSW.
Layout
| Path | Responsibility |
|---|---|
Blueprint/DemoBlueprint.php | The whole dataset as plain data — channels, category trees, products, manufacturers, properties, tags. Touches no Shopware API. |
Blueprint/PeopleBlueprint.php | Customers, where they live, order state mix. |
Seeder/* | One class per entity type (sales channels, categories, footer menus, products, manufacturers, properties, tags, media, tax, price rules, landing pages, customers, customer groups, orders, cross-selling). Each inspects before it writes. |
Seeder/CategoryWriter | The only place a category row is created or topped up. |
Service/DemoDataSeeder | Runs the seeders in dependency order. |
Service/EntityResolver | The inspect-before-write decision. |
Service/DemoIdGenerator | Stable, namespaced UUIDs — the basis of idempotency. |
Service/DeterministicValueGenerator | Reproducible pseudo-randomness. |
Service/ProductPayloadBuilder, ProductReviewBuilder, ProductNameGenerator | Pure builders, unit-tested. |
Service/SeedStatusStore | Last-run status, kept in system config (no migration). |
Command/* | kmh:demo-data:seed, kmh:demo-data:status, kmh:demo-data:user. |
MessageQueue/* | GenerateDemoDataMessage + handler for Administration runs. |
Administration/Controller/DemoDataController | Queue a run, read status, create the demo user. |
Installer/CustomFieldsInstaller | Provenance custom fields on product and category. |
To extend the dataset — another channel, category or product line — edit DemoBlueprint and nothing else.
Idempotency
- Deterministic IDs. Every entity's UUID is derived from a namespace, entity type and hierarchical blueprint path, so the same node always maps to the same row — and the same category name under two channels maps to two rows.
- Look twice before writing.
EntityResolverlooks up the plugin's deterministic ID, then the natural key (name, product number, tax rate). A match under a foreign ID is adopted, not duplicated. - Narrow writes to existing rows. Scalars are filled only where empty; associations are diffed and only missing links added; nothing is unlinked; no write at all when nothing is missing.
- Sibling order uses
afterCategoryId(category has no position column). - Adopted products are protected: no generated reviews or cross-selling on a merchant's real product.
Sales channels are resolved by deterministic ID, then by name, then by the blueprint's adopt list (flagship adopts Storefront). A channel is only created when nothing matches, cloning language, currency, payment and shipping from an existing storefront. An adopted channel keeps its navigation category.
CLI commands
| Command | Purpose | Options |
|---|---|---|
kmh:demo-data:seed | Create or complete the demo catalogue. Non-interactive; prints a per-entity tally. | -c/--channel <key> (repeatable), -p/--per-category <n>, --skip-orders, --skip-media |
kmh:demo-data:status | Report what already exists. Writes nothing. | — |
kmh:demo-data:user | Create or report the read-only Administration user. | --email, --username, --password, --rotate-password, --show |
Merchant-facing usage: Generating demo data, Read-only demo account.
Background processing
Runs started from the Administration dispatch GenerateDemoDataMessage to Shopware's async transport; its handler runs the same DemoDataSeeder as the CLI. SeedStatusStore keeps the run state in system config, which the Administration polls and which blocks a second concurrent run. See Shopware: Message queue.
Admin API
| Method & path | Privilege | Purpose |
|---|---|---|
POST /api/_action/kmh-demo-data/generate | kmh_demo_data:generate | Queue a run (options as in the UI). Refused while a run is active. |
GET /api/_action/kmh-demo-data/status | kmh_demo_data:generate | Status of the current / last run. |
POST /api/_action/kmh-demo-data/demo-user | kmh_demo_data:manage_user | Create the read-only Administration user. |
Custom fields
Set kmh_demo_data on product and category: kmh_demo_data_source_key, kmh_demo_data_generated, kmh_demo_data_channel_key. Keys live in Util/DemoDataConstants. Removed on uninstall only when data is not kept.
Development setup & testing
bash
git clone https://github.com/KommandHub/KmhDemoDataSW.git
cd KmhDemoDataSW
make up # Shopware + this plugin in container `kommandhub-demodata-plugin`
make shell # then: bin/console plugin:install --activate KmhDemoDataSW
make cs-fix && make analyse && make test # the gate to pass before every commit
make test FILTER=SomeTest
make test-coverage
make validate-plugin # Shopware Store compliance (shopware-cli, inside the container)
make zip # release ZIP into build/tests/Unitmirrorssrc/and needs no kernel; tests that boot Shopware carry#[Group('kernel')]and are excluded in CI.- CI (GitHub Actions,
.github/workflows/php.yml) runs composer validate, PHP lint, PHPStan level 9, php-cs-fixer and PHPUnit, and enforces 100 % line coverage. - Blueprint invariants (every category can reach the target count, contiguous price tiers, order totals add up) are unit-tested. Idempotency was verified by running: cold run, repeat runs (0 created / 0 enriched), an enrichment run, and duplicate checks.
make downdeletes the stack's database volume; the stack publishes no host port by default (addports: ["80:80"]to reach the shop in a browser). Shared tooling: Development environment.