97 lines
4.5 KiB
PHP
97 lines
4.5 KiB
PHP
<?php
|
|
|
|
namespace App\BusProNet\XmlParser;
|
|
|
|
use App\BusProNet\ApiClient;
|
|
use App\BusProNet\Exception\ResponseParserException;
|
|
use Symfony\Component\DomCrawler\Crawler;
|
|
|
|
class ApiResponseParser extends AbstractParser
|
|
{
|
|
/**
|
|
* @throws ResponseParserException
|
|
*/
|
|
/** @param array<string, mixed> $additionalArgs */
|
|
public function parseXmlString(string $type, string $xml, array $additionalArgs = []): mixed
|
|
{
|
|
$crawler = new Crawler($xml);
|
|
|
|
if (0 === $crawler->count()) {
|
|
throw new ResponseParserException('Empty response received from server');
|
|
}
|
|
|
|
// Override type unless present in XML to catch error responses
|
|
$responseType = $this
|
|
->getStringOrNullValue($crawler->filterXPath('//ergebnis/satz/@typ')) ?? $type;
|
|
|
|
$resultNode = $crawler->filterXPath('//ergebnis');
|
|
|
|
try {
|
|
switch ($responseType) {
|
|
case ApiClient::TYPE_NOTIFICATION:
|
|
return (new NotificationParser())->parse($crawler);
|
|
case ApiClient::TYPE_CUSTOMER_DATA:
|
|
$subType = $this->getStringOrNullValue($resultNode->filterXPath('//art'));
|
|
if (null === $subType || '' === $subType) {
|
|
throw new ResponseParserException('Unable to determine customer data subtype from XML response');
|
|
}
|
|
|
|
switch ($subType) {
|
|
case 'Adressdaten':
|
|
case 'Adressdaten_Ändern':
|
|
case 'Newsletter':
|
|
return (new PersonalDataParser())->parse($resultNode);
|
|
case 'Adresse_Neu':
|
|
return (new ContactFormResponseParser())->parse($resultNode);
|
|
case 'SelektionCRM':
|
|
case 'SelektionCRM_Ändern':
|
|
return (new CrmAttributesResponseParser())->parse($resultNode);
|
|
case 'Vorgänge':
|
|
return (new BookingsParser())->parse($resultNode);
|
|
case 'Vorgang_Details':
|
|
return (new BookingParser())->parse($resultNode);
|
|
case 'Dokumentdruck':
|
|
return (new DocumentsParser())->parseDocuments($resultNode);
|
|
case 'Vorgangdruck':
|
|
return (new DocumentsParser())->parseConfirmation($resultNode);
|
|
}
|
|
break;
|
|
case ApiClient::TYPE_BASE_DATA_COUNTRIES:
|
|
return (new CountriesParser())->parse($resultNode);
|
|
case ApiClient::TYPE_MUTABLE_DATA:
|
|
return (new MutableDataParser())->parse($resultNode);
|
|
case ApiClient::TYPE_AVAILABILITY:
|
|
return (new AvailabilitiesParser())->parseServices($resultNode);
|
|
case ApiClient::TYPE_AVAILABILITY_EXTENDED:
|
|
return (new ExtendedAvailabilitiesParser())->parseServices($resultNode);
|
|
case ApiClient::TYPE_AVAILABILITY_HOTEL:
|
|
return (new AvailabilitiesParser())->parseRooms($resultNode);
|
|
case ApiClient::TYPE_BOOKING_UPDATE:
|
|
return (new BookingUpdateParser())->parse($resultNode);
|
|
case ApiClient::TYPE_BOOKING:
|
|
return (new BookingResponseParser())->parse($resultNode);
|
|
case ApiClient::TYPE_PRODUCTS:
|
|
return (new ProductsParser())->parse($resultNode);
|
|
case ApiClient::TYPE_PRODUCT_DATA:
|
|
$travelNode = $crawler->filterXPath('//reise/termin');
|
|
|
|
if (0 === $travelNode->count()) {
|
|
throw new ResponseParserException('No travel data node found in product data response');
|
|
}
|
|
|
|
return (new TravelParser())->parse($travelNode->first(), ...$additionalArgs);
|
|
case ApiClient::TYPE_AGENCIES:
|
|
return (new AgencyParser())->parse($resultNode);
|
|
case ApiClient::TYPE_PURCHASE_VOUCHER:
|
|
return (new PurchaseVoucherParser())->parse($resultNode);
|
|
case ApiClient::TYPE_PROMO_VOUCHER:
|
|
return (new PromoVoucherParser())->parse($resultNode);
|
|
}
|
|
} catch (\InvalidArgumentException $e) {
|
|
throw new ResponseParserException('Invalid XML response structure: '.$e->getMessage(), 0, $e);
|
|
}
|
|
|
|
throw new ResponseParserException('Unable to parse XML response');
|
|
}
|
|
}
|