145 lines
4.1 KiB
PHP
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;
|
|
}
|
|
}
|