Skip to main content
Version: Next

Events

Listen to these events to change what an export does without replacing the exporter service. They fall into three groups: events fired during an export, events fired when a configuration is saved or deleted, and pre-response events of the Pimcore Studio endpoints.

Export Events

These events surround an export run, from evaluating a save hook to delivering the finished file. They live in the Pimcore\Bundle\DataHubFileExportBundle\Event namespace, and each one exposes the exporter through getExporter().

EventDispatchedUse it to
IsValidDataObjectTriggerEventWhen a data object change is evaluated for triggering an export.Suppress an export run for a specific change. Read the triggering event with getTriggerEvent(), then setIsValid(false).
RelevantItemListEventAfter the listing of items to export is built, before its IDs are loaded.Narrow or extend the listing with getList() and setList().
IsValidExportItemEventFor each item, before it is exported.Skip a single item with setIsValid(false).
FilterExistingDataEventOn every run that is not a full export, after the previously exported rows are re-read and rows that are no longer valid have been dropped.Remove further rows with getData() and setData().
PreWriteDataEventAfter new and existing rows are merged, before they are written to the output file.Reshape the rows with getData() and setData().
FilenameEventAfter the filename and its date placeholder are resolved.Change the name with getFilename() and setFilename().
TransmissionFailedEventWhen a transmitter fails to deliver the finished file. The original exception is re-thrown afterwards, so existing error handling still applies.React to a failed delivery, for example by notifying an administrator. Read getTransmitterType() and getException().
note

A run counts as a full export only when it resolves the items itself: Run Full Export, Cron (Full Export), and the CLI command without --only-queue-items. Queue-only runs and the Full Export on Save save hook both leave isFullExport at false, so FilterExistingDataEvent fires for them as well.

Configuration Events

These two events fire when a configuration is saved or deleted in Pimcore Studio. They live in the Pimcore\Bundle\DataHubFileExportBundle\Event\Admin namespace and do not carry an exporter.

EventDispatchedUse it to
ValidateConfigEventBefore a configuration is saved.Reject invalid settings. Read them with getConfigData() and throw an exception; it is converted into a validation error shown to the user.
ResetConfigEventAfter a configuration is deleted, and after a save triggered by Save, reset and clear queue.Clean up your own state. getConfig() returns the configuration, getContext() returns ['source' => 'delete'] or ['source' => 'save'].

Studio API Events

The configuration panel is a Pimcore Studio plugin. Before one of its endpoints returns, the bundle dispatches a pre-response event carrying the response schema. Listen for it to add your own data to the response.

Event nameReturned data
pre_response.data_hub_file_export.configuration_detailA single export configuration.
pre_response.data_hub_file_export.configuration_updateThe configuration after it was saved.
pre_response.data_hub_file_export.cron_validation_resultThe result of validating a cron expression.
pre_response.data_hub_file_export.export_progressThe progress of a running export.
pre_response.data_hub_file_export.exporter_serviceOne selectable custom exporter service.
pre_response.data_hub_file_export.exporter_typeOne selectable export file type.
pre_response.data_hub_file_export.thumbnail_itemOne selectable thumbnail.

See the Studio Backend Additional and Custom Attributes documentation for the listener pattern.

warning

The endpoints themselves are not a supported public API. Their controllers are marked @internal and may change in any release without a deprecation path. Do not build integrations against them.

Registering a Listener

App\EventListener\DataHubFileExportListener:
tags:
- { name: kernel.event_listener, event: Pimcore\Bundle\DataHubFileExportBundle\Event\IsValidExportItemEvent, method: isValidExportItem }
- { name: kernel.event_listener, event: Pimcore\Bundle\DataHubFileExportBundle\Event\FilterExistingDataEvent, method: filterExistingData }
- { name: kernel.event_listener, event: Pimcore\Bundle\DataHubFileExportBundle\Event\PreWriteDataEvent, method: preWriteData }
- { name: kernel.event_listener, event: Pimcore\Bundle\DataHubFileExportBundle\Event\RelevantItemListEvent, method: relevantItemList }
- { name: kernel.event_listener, event: Pimcore\Bundle\DataHubFileExportBundle\Event\FilenameEvent, method: modifyFilename }
- { name: kernel.event_listener, event: Pimcore\Bundle\DataHubFileExportBundle\Event\TransmissionFailedEvent, method: transmissionFailed }

Sample Listener

<?php

/**
* This source file is available under the terms of the
* Pimcore Open Core License (POCL)
* Full copyright and license information is available in
* LICENSE.md which is distributed with this source code.
*
* @copyright Copyright (c) Pimcore GmbH (https://www.pimcore.com)
* @license Pimcore Open Core License (POCL)
*/

namespace App\EventListener;

use Pimcore\Bundle\DataHubFileExportBundle\Event\FilenameEvent;
use Pimcore\Bundle\DataHubFileExportBundle\Event\FilterExistingDataEvent;
use Pimcore\Bundle\DataHubFileExportBundle\Event\IsValidExportItemEvent;
use Pimcore\Bundle\DataHubFileExportBundle\Event\PreWriteDataEvent;
use Pimcore\Bundle\DataHubFileExportBundle\Event\RelevantItemListEvent;
use Pimcore\Bundle\DataHubFileExportBundle\Event\TransmissionFailedEvent;
use Pimcore\Db;
use Pimcore\Log\ApplicationLogger;
use Pimcore\Model\DataObject;

class DataHubFileExportListener
{
// Uppercase the name of the exported file.
public function modifyFilename(FilenameEvent $event): void
{
$event->setFilename(strtoupper($event->getFilename()));
}

// Exclude one specific object from the export.
public function isValidExportItem(IsValidExportItemEvent $event): void
{
if ($event->getObject()->getId() === 82) {
$event->setIsValid(false);
}
}

// Restrict the exported listing with an additional SQL condition.
public function relevantItemList(RelevantItemListEvent $event): void
{
$list = $event->getList();
$db = Db::get();
$idColumn = DataObject\Service::getVersionDependentDatabaseColumnName('o_id');

$ownCondition = $db->quoteIdentifier($idColumn) . ' = 123';
$existing = $list->getCondition();

// The workspace condition is empty without workspaces and an unparenthesized OR chain with several of them,
// so it has to be grouped before an AND is appended.
$list->setCondition($existing ? '(' . $existing . ') AND ' . $ownCondition : $ownCondition);
$event->setList($list);
}

// Prefix every exported name before the rows are written.
public function preWriteData(PreWriteDataEvent $event): void
{
$data = $event->getData();

foreach ($data as $i => $row) {
// For CSV the first row is the numeric header row, and advanced schemas may omit the column entirely.
if (!array_key_exists('name', $row)) {
continue;
}

$row['name'] = 'hello - ' . $row['name'];
$data[$i] = $row;
}

$event->setData($data);
}

// Drop rows whose object no longer passes the export validation.
public function filterExistingData(FilterExistingDataEvent $event): void
{
$exporter = $event->getExporter();
$data = $event->getData();

foreach ($data as $i => $row) {
$object = DataObject\Concrete::getById($row['id']);
if (!$exporter->isValidExportItem($object)) {
unset($data[$i]);
}
}

$event->setData($data);
}

// Log a failed delivery of the finished file.
public function transmissionFailed(TransmissionFailedEvent $event): void
{
$configName = $event->getExporter()->getDataHubConfiguration()->getName();

ApplicationLogger::getInstance()->error(
sprintf(
'Transmission "%s" failed for config "%s": %s',
$event->getTransmitterType(),
$configName,
$event->getException()?->getMessage()
)
);
}
}