feat: webhook form finisher for generic post requests

addresses #869cupm97
This commit is contained in:
Björn Fromme
2026-06-16 11:18:07 +02:00
parent 90a5fab2fa
commit 9933a0d3f7
6 changed files with 129 additions and 23 deletions
@@ -0,0 +1,43 @@
<?php
namespace EP\EpTheme\Form;
use TYPO3\CMS\Core\Log\LogManager;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
abstract class AbstractMappedFinisher extends AbstractFinisher
{
protected function buildPayload(): array
{
$values = [];
$formValues = $this->finisherContext->getFormValues();
$mappingOption = (string)$this->parseOption('mapping');
$mappings = GeneralUtility::trimExplode(',', $mappingOption, true);
foreach ($mappings as $mapping) {
$parts = GeneralUtility::trimExplode(':', $mapping, true, 2);
if (2 !== count($parts)) {
continue;
}
[$remote, $local] = $parts;
if ('' === $remote || '' === $local || false === array_key_exists($local, $formValues)) {
continue;
}
$values[$remote] = $formValues[$local];
}
return $values;
}
protected function logWarning(string $message, array $context = []): void
{
GeneralUtility::makeInstance(LogManager::class)
->getLogger(static::class)
->warning($message, array_merge([
'finisher' => static::class,
], $context));
}
}
@@ -3,10 +3,8 @@
namespace EP\EpTheme\Form;
use EP\EpProducts\MyEP\ApiClient;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Form\Domain\Finishers\AbstractFinisher;
class BpnApiFinisher extends AbstractFinisher
class BpnApiFinisher extends AbstractMappedFinisher
{
/**
* @var ApiClient
@@ -24,30 +22,14 @@ class BpnApiFinisher extends AbstractFinisher
protected function executeInternal()
{
try {
$values = [];
$formValues = $this->finisherContext->getFormValues();
$mappingOption = (string)$this->parseOption('mapping');
$mappings = GeneralUtility::trimExplode(',', $mappingOption, true);
foreach ($mappings as $mapping) {
$parts = GeneralUtility::trimExplode(':', $mapping, true, 2);
if (2 !== count($parts)) {
continue;
}
[$remote, $local] = $parts;
if ('' === $remote || '' === $local || false === array_key_exists($local, $formValues)) {
continue;
}
$values[$remote] = $formValues[$local];
}
$values = $this->buildPayload();
if ([] !== $values) {
$this->apiClient->registerAddress($values);
}
} catch (\Throwable $e) {
// Intentionally ignore all errors so the form submission stays silent.
$this->logWarning('Bpn API finisher request failed.', [
'exception' => $e,
]);
}
}
}
@@ -0,0 +1,40 @@
<?php
namespace EP\EpTheme\Form;
use Symfony\Component\HttpClient\HttpClient;
use TYPO3\CMS\Core\Utility\GeneralUtility;
class WebhookFinisher extends AbstractMappedFinisher
{
protected function executeInternal()
{
try {
$url = trim((string)$this->parseOption('url'));
if ('' === $url) {
return;
}
$payload = $this->buildPayload();
if ([] === $payload) {
return;
}
$response = HttpClient::create()->request('POST', $url, [
'json' => $payload,
]);
$statusCode = $response->getStatusCode();
if ($statusCode < 200 || $statusCode >= 300) {
$this->logWarning('Webhook finisher returned an unexpected response status.', [
'url' => $url,
'statusCode' => $statusCode,
]);
}
} catch (\Throwable $e) {
$this->logWarning('Webhook finisher request failed.', [
'exception' => $e,
]);
}
}
}