Appearance
Extension points
For developers
Other plugins extend exports without decorating internal services. The events, their objects and the tagged interfaces below are the plugin's public extension API. Rule of thumb: events to customise a step, tagged interfaces to add a whole strategy, state-machine events to react to lifecycle changes.
Events
All are dispatched on Shopware's event_dispatcher; subscribe by class name.
OrderExportCriteriaEvent
Kommandhub\OrderExport\Shopware\Export\Event\OrderExportCriteriaEvent
- When: before the order is loaded, after the core associations and the ID filter are set.
- Exposes:
getCriteria(): Criteria(mutable),getOrderId(),getContext(). - Use it to add associations, filters or sorting. Only add — never reset IDs or replace the association set. Subscribers share one instance and one query, so keep additions to what you export.
OrderExportProjectionEvent
Kommandhub\OrderExport\Shopware\Export\Event\OrderExportProjectionEvent
- When: after the order is projected into the
order.*array. - Exposes:
getProjection(),set(string $key, mixed $value),mergeData(array $data),getOrder(): OrderEntity,getContext(). - Use it to add computed or cross-entity values. You do not need it just to reach an association — load it with the criteria event and it is already in the projection. Do not query here; keep values deterministic (the payload is hashed for de-duplication).
OrderExportRequestEvent
Kommandhub\OrderExport\Shopware\Export\Event\OrderExportRequestEvent
- When: in the HTTP transport, after authentication, before sending.
- Exposes:
getRequest(): RequestBuilder(mutable),getEndpoint(): EndpointConfig. - Use it to add cross-cutting headers or a body signature:
$event->getRequest()->withHeader('X-Tenant', 'acme'). Do not change the endpoint URL; for a new auth scheme implement an authenticator.
Example
php
use Kommandhub\OrderExport\Shopware\Export\Event\OrderExportCriteriaEvent;
use Kommandhub\OrderExport\Shopware\Export\Event\OrderExportProjectionEvent;
use Kommandhub\OrderExport\Shopware\Export\Event\OrderExportRequestEvent;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
final class ExportEnrichmentSubscriber implements EventSubscriberInterface
{
public static function getSubscribedEvents(): array
{
return [
OrderExportCriteriaEvent::class => 'onCriteria',
OrderExportProjectionEvent::class => 'onProjection',
OrderExportRequestEvent::class => 'onRequest',
];
}
public function onCriteria(OrderExportCriteriaEvent $event): void
{
$event->getCriteria()->addAssociation('lineItems.product');
}
public function onProjection(OrderExportProjectionEvent $event): void
{
$numbers = $event->getOrder()->getDocuments()?->map(
static fn ($document) => $document->getConfig()['documentNumber'] ?? null,
) ?? [];
$event->set('documentNumbers', array_values(array_filter($numbers)));
}
public function onRequest(OrderExportRequestEvent $event): void
{
$event->getRequest()->withHeader('X-Tenant', 'acme');
}
}Mappings can then use order.documentNumbers and item.product.ean.
Tagged interfaces (add a strategy)
Implement, tag, and the matching registry selects it by its key — adding one never disturbs the others.
Interface (Kommandhub\OrderExport\Domain\…) | Tag | Selected by | Add… |
|---|---|---|---|
Transport\TransportInterface | kmh.transport | target transportType | a protocol (SFTP, AMQP…) |
Auth\AuthenticatorInterface | kmh.authenticator | credential authType | an auth scheme |
Ack\AcknowledgementStrategyInterface | kmh.ack_strategy | target ackMode | an acknowledgement style |
Payload\PayloadSerializer | kmh.payload.serializer | mapping targetFormat | an output format (CSV…) |
Mapping\Expression\TransformerInterface | kmh.mapping.transformer | its name() | a mapping function |
Adding a mapping function
A transformer example:
php
use Kommandhub\OrderExport\Domain\Mapping\Expression\TransformerInterface;
final class Upper implements TransformerInterface
{
public function name(): string { return 'upper'; }
public function __invoke(mixed ...$args): mixed
{
return strtoupper((string) ($args[0] ?? ''));
}
}xml
<service id="Acme\Export\Upper">
<tag name="kmh.mapping.transformer"/>
</service>Transformers run inside the mapping sandbox: keep them pure (no I/O, no database) and deterministic.
A new transport, authenticator or serialiser also needs its key selectable in the Administration forms, which currently list only the built-in options — set it through the Admin API until then.
Lifecycle
React to export state changes with Shopware's state-machine events on kmh_order_export.state:
state_machine.kmh_order_export.state.state_changedstate_enter.kmh_order_export.state.failed,…acknowledged, etc.
The transitioned entity carries the attempt history, including the failure reason.
Flow Builder
The plugin's action is action.kmh.export_order (config: configId). Your own Flow actions can dispatch exports through Kommandhub\OrderExport\Shopware\Export\ExportDispatcher::dispatch($orderId, $configId, $context).