Files
myep/src/Command/BpnReplayCommand.php
T

145 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Command;
use App\BusProNet\ApiClient;
use App\BusProNet\Exception\ApiClientException;
use Symfony\Component\Console\Attribute\AsCommand;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
#[AsCommand(
name: 'app:bpn:replay',
description: 'Replay a BPN API request from an XML file',
)]
class BpnReplayCommand extends Command
{
public function __construct(
private readonly ApiClient $apiClient,
) {
parent::__construct();
}
protected function configure(): void
{
$this
->addArgument('file', InputArgument::REQUIRED, 'Path to the XML request file')
->addOption('dry-run', 'd', InputOption::VALUE_NONE, 'Show regenerated XML without sending')
->addOption('output', 'o', InputOption::VALUE_REQUIRED, 'Save response to file')
;
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$filePath = $input->getArgument('file');
if (false === file_exists($filePath)) {
$io->error(sprintf('File not found: %s', $filePath));
return Command::FAILURE;
}
$xml = file_get_contents($filePath);
if (false === $xml) {
$io->error(sprintf('Unable to read file: %s', $filePath));
return Command::FAILURE;
}
$io->info(sprintf('Loaded XML from: %s', $filePath));
$type = $this->extractRequestType($xml);
if (null !== $type) {
$io->info(sprintf('Request type: %s', $type));
}
if (true === $input->getOption('dry-run')) {
$regeneratedXml = $this->regenerateKey($xml);
if (null === $regeneratedXml) {
$io->error('Failed to regenerate key in XML');
return Command::FAILURE;
}
$io->section('Regenerated XML (dry-run)');
$io->writeln($this->formatXml($regeneratedXml));
return Command::SUCCESS;
}
$io->info('Sending request to BPN API...');
try {
$response = $this->apiClient->sendRawXml($xml);
} catch (ApiClientException $e) {
$io->error(sprintf('API request failed: %s', $e->getMessage()));
return Command::FAILURE;
}
$outputFile = $input->getOption('output');
if (null !== $outputFile) {
if (false === file_put_contents($outputFile, $response)) {
$io->error(sprintf('Failed to write response to: %s', $outputFile));
return Command::FAILURE;
}
$io->success(sprintf('Response saved to: %s', $outputFile));
}
$io->section('Response');
$io->writeln($this->formatXml($response));
return Command::SUCCESS;
}
private function extractRequestType(string $xml): ?string
{
$doc = new \DOMDocument();
if (false === @$doc->loadXML($xml)) {
return null;
}
$satzNode = $doc->getElementsByTagName('satz')->item(0);
return $satzNode?->getAttribute('typ');
}
private function regenerateKey(string $xml): ?string
{
$doc = new \DOMDocument();
if (false === @$doc->loadXML($xml)) {
return null;
}
$keyNode = $doc->getElementsByTagName('key')->item(0);
if (null === $keyNode) {
return null;
}
$keyNode->nodeValue = '[KEY_WOULD_BE_REGENERATED]';
return $doc->saveXML();
}
private function formatXml(string $xml): string
{
$doc = new \DOMDocument();
$doc->preserveWhiteSpace = false;
$doc->formatOutput = true;
if (false === @$doc->loadXML($xml)) {
return $xml;
}
return $doc->saveXML() ?: $xml;
}
}