feat: refactoring of xml parsers
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
abstract class AbstractParser
|
||||
{
|
||||
use TypeConversionTrait;
|
||||
|
||||
protected function getStringOrNullValue(Crawler $node): ?string
|
||||
{
|
||||
return 0 < $node->count() ? $node->text() : null;
|
||||
}
|
||||
|
||||
protected function getIntOrNullValue(Crawler $node): ?int
|
||||
{
|
||||
return 0 < $node->count() ? (int) $node->text() : null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
<?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
|
||||
*/
|
||||
public function parseXmlString(string $type, string $xml): mixed
|
||||
{
|
||||
$crawler = new Crawler($xml);
|
||||
|
||||
if (0 === $crawler->count()) {
|
||||
throw new ResponseParserException('Empty response received from server');
|
||||
}
|
||||
|
||||
// Override type when present in XML to catch error responses
|
||||
$responseType = $this
|
||||
->getStringOrNullValue($crawler->filterXPath('//ergebnis/satz/@typ')) ?? $type;
|
||||
|
||||
$resultNode = $crawler->filterXPath('//ergebnis');
|
||||
|
||||
switch ($responseType) {
|
||||
case ApiClient::TYPE_NOTIFICATION:
|
||||
return (new NotificationParser())->parse($crawler);
|
||||
case ApiClient::TYPE_CUSTOMER_DATA:
|
||||
$subType = $resultNode->filterXPath('//art')->text();
|
||||
|
||||
switch ($subType) {
|
||||
case 'Adressdaten':
|
||||
case 'Adressdaten_Ändern':
|
||||
case 'Newsletter':
|
||||
return (new PersonalDataParser())->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())->parse($resultNode);
|
||||
case ApiClient::TYPE_BOOKING_UPDATE:
|
||||
return (new BookingUpdateParser())->parse($resultNode);
|
||||
}
|
||||
|
||||
throw new ResponseParserException('Unable to parse XML response');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Availability;
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class AvailabilitiesParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): BaseData
|
||||
{
|
||||
$availabilities = [];
|
||||
|
||||
$result
|
||||
->filterXPath('//leistungen/leistung')
|
||||
->each(function (Crawler $node) use (&$availabilities) {
|
||||
$availability = new Availability();
|
||||
$availability->serviceId = (int) $node->attr('id');
|
||||
$availability->status = $node->attr('status');
|
||||
$availability->available = (int) $node->attr('frei');
|
||||
$availability->price = $this->stringToFloat($node->attr('preis'));
|
||||
|
||||
$availabilities[$availability->serviceId] = $availability;
|
||||
})
|
||||
;
|
||||
|
||||
return new BaseData($availabilities);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,155 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Address;
|
||||
use App\BusProNet\Model\Booking;
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\BusProNet\Model\PersonalData;
|
||||
use App\BusProNet\Model\Service;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class BookingParser extends AbstractParser
|
||||
{
|
||||
private readonly ServicesParser $servicesParser;
|
||||
private readonly RoomsParser $roomsParser;
|
||||
private readonly PickupsParser $pickupsParser;
|
||||
private readonly SurchargesParser $surchargesParser;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->servicesParser = new ServicesParser();
|
||||
$this->roomsParser = new RoomsParser();
|
||||
$this->pickupsParser = new PickupsParser();
|
||||
$this->surchargesParser = new SurchargesParser();
|
||||
}
|
||||
|
||||
public function parse(Crawler $node): Booking
|
||||
{
|
||||
$booking = new Booking();
|
||||
|
||||
$booking->id = $this->getIntOrNullValue($node->filterXPath('//idbuchung'));
|
||||
$booking->agencyId = $this->getIntOrNullValue($node->filterXPath('//idagentur'));
|
||||
$booking->bookingNumber = $this->getIntOrNullValue($node->filterXPath('//vorgang'));
|
||||
$booking->invoiceNumber = $this->getIntOrNullValue($node->filterXPath('//zahlungsdaten/rechnung'));
|
||||
$booking->totalPrice = $this
|
||||
->stringToFloat($this->getStringOrNullValue($node->filterXPath('//zahlungsdaten/gesamtbetrag')));
|
||||
$booking->status = $this->getStringOrNullValue($node->filterXPath('//status'));
|
||||
|
||||
$travelData = $node->filterXPath('//reise');
|
||||
|
||||
$booking->travel = $travelData->attr('bezeichnung');
|
||||
$booking->travelId = $this->getIntOrNullValue($node->filterXPath('//idreise'));
|
||||
$booking->travelCode = $travelData->attr('code');
|
||||
$booking->travelDate = $this->stringToDate($travelData->attr('termin'));
|
||||
|
||||
$booking->hotelId = $this->getIntOrNullValue($node->filterXPath('//idpartner'));
|
||||
$booking->hotelName = $this->getStringOrNullValue($node->filterXPath('//partner'));
|
||||
|
||||
$booking->applicant = $this->parsePersonalData($node->filterXPath('//anmelder'));
|
||||
|
||||
$participantsStatus = $this
|
||||
->stringToArray($this->getStringOrNullValue($node->filterXPath('//status_teilnehmer')), '/');
|
||||
$booking->participantsStatus = array_combine(range(1, count($participantsStatus)), $participantsStatus);
|
||||
|
||||
$booking->participants = $this->parseParticipants($node->filterXPath('//teilnehmerliste/teilnehmer'));
|
||||
|
||||
$paymentData = $node->filterXPath('//zahlung');
|
||||
$booking->paymentId = (int) $paymentData->attr('idzahlungsart');
|
||||
$booking->paymentLabel = $paymentData->attr('bezeichnung');
|
||||
$booking->paymentType = $paymentData->attr('art');
|
||||
|
||||
$transportationData = $node->filterXPath('//beförderungen/beförderung');
|
||||
if (0 < $transportationData->count()) {
|
||||
$booking->transportationServices = $this
|
||||
->servicesParser
|
||||
->parse($transportationData, Service::CATEGORY_TRANSPORTATION, Service::SOURCE_BOOKING);
|
||||
}
|
||||
|
||||
$additionalServicesData = $node->filterXPath('//zusatzleistungen/zusatzleistung');
|
||||
if (0 < $additionalServicesData->count()) {
|
||||
$booking->additionalServices = $this
|
||||
->servicesParser
|
||||
->parse($additionalServicesData, Service::CATEGORY_ADDITIONAL, Service::SOURCE_BOOKING);
|
||||
}
|
||||
|
||||
$roomsData = $node->filterXPath('//ferienzielunterbringungen/ferienzielunterbringung');
|
||||
if (0 < $roomsData->count()) {
|
||||
$booking->rooms = $this->roomsParser->parse($roomsData);
|
||||
}
|
||||
|
||||
$pickupsData = $node->filterXPath('//zustiege/zustieg');
|
||||
if (0 < $pickupsData->count()) {
|
||||
$booking->pickups = $this->pickupsParser->parse($pickupsData);
|
||||
}
|
||||
|
||||
$surchargesData = $node->filterXPath('//zuschlaege/zuschlag');
|
||||
if (0 < $surchargesData->count()) {
|
||||
$booking->surcharges = $this->surchargesParser->parse($surchargesData);
|
||||
}
|
||||
|
||||
return $booking;
|
||||
}
|
||||
|
||||
private function parseParticipants(Crawler $node): array
|
||||
{
|
||||
$participants = [];
|
||||
|
||||
$node->each(function (Crawler $node) use (&$participants) {
|
||||
$id = (int) $node->attr('id');
|
||||
$participants[$id] = $this->parsePersonalData($node);
|
||||
});
|
||||
|
||||
return $participants;
|
||||
}
|
||||
|
||||
private function parsePersonalData(Crawler $node): PersonalData
|
||||
{
|
||||
$personalData = new PersonalData();
|
||||
|
||||
$personalData->addressId = $this->getIntOrNullValue($node->filterXPath('//idadresse'));
|
||||
$personalData->personId = $this->getIntOrNullValue($node->filterXPath('//idadresseperson'));
|
||||
|
||||
$dateString = $this->getStringOrNullValue($node->filterXPath('//geburtsdatum'));
|
||||
$personalData->dateOfBirth = null !== $dateString
|
||||
? \DateTimeImmutable::createFromFormat('d.m.Y', $dateString) : null;
|
||||
|
||||
$personalData->firstName = $this->getStringOrNullValue($node->filterXPath('//vorname'));
|
||||
$personalData->name = $this->getStringOrNullValue($node->filterXPath('//name'));
|
||||
$personalData->salutation = $this->getStringOrNullValue($node->filterXPath('//anrede'));
|
||||
$personalData->title = $this->getStringOrNullValue($node->filterXPath('//titel'));
|
||||
$genderValue = $this->getStringOrNullValue($node->filterXPath('//geschlecht'));
|
||||
$personalData->gender = null !== $genderValue ? strtoupper($genderValue) : null;
|
||||
|
||||
$personalData->height = $this->getStringOrNullValue($node->filterXPath('//sonstiges1'));
|
||||
$personalData->weight = $this->getStringOrNullValue($node->filterXPath('//sonstiges2'));
|
||||
$personalData->shoeSize = $this->getStringOrNullValue($node->filterXPath('//sonstiges3'));
|
||||
|
||||
$addressNode = $node->filterXPath('//anschrift');
|
||||
|
||||
if (0 < $addressNode->count()) {
|
||||
$address = new Address();
|
||||
$address->street = $this->getStringOrNullValue($addressNode->filterXPath('//strasse'));
|
||||
$address->postCode = $this->getStringOrNullValue($addressNode->filterXPath('//plz'));
|
||||
$address->city = $this->getStringOrNullValue($addressNode->filterXPath('//ort'));
|
||||
$address->country = $this->getStringOrNullValue($addressNode->filterXPath('//land'));
|
||||
|
||||
$personalData->address = $address;
|
||||
}
|
||||
|
||||
$contactNode = $node->filterXPath('//kommunikation');
|
||||
|
||||
if (0 < $contactNode->count()) {
|
||||
$communication = new Communication();
|
||||
$communication->phone = $this->getStringOrNullValue($contactNode->filterXPath('//telefonprivat'));
|
||||
$communication->mobile = $this->getStringOrNullValue($contactNode->filterXPath('//telefonmobil'));
|
||||
$communication->email = $this->getStringOrNullValue($contactNode->filterXPath('//email'));
|
||||
$communication->newsletter = $this
|
||||
->stringToBool($contactNode->filterXPath('//newsletter')->text('False'));
|
||||
|
||||
$personalData->communication = $communication;
|
||||
}
|
||||
|
||||
return $personalData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\BookingUpdate;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class BookingUpdateParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $node): BookingUpdate
|
||||
{
|
||||
$bookingUpdate = new BookingUpdate();
|
||||
$bookingUpdate->valid = 'möglich' === $node->filterXPath('//aenderung')->text();
|
||||
$bookingUpdate->totalPrice = $this->stringToFloat($node->filterXPath('//gesamtpreis')->text());
|
||||
|
||||
return $bookingUpdate;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\Booking;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class BookingsParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): BaseData
|
||||
{
|
||||
$bookings = [];
|
||||
$items = $result->filterXPath('//vorgaenge/vorgang');
|
||||
|
||||
if (0 === $items->count()) {
|
||||
return new BaseData($bookings);
|
||||
}
|
||||
|
||||
$items->each(function (Crawler $node) use (&$bookings) {
|
||||
$booking = new Booking();
|
||||
|
||||
$booking->id = $this->getIntOrNullValue($node->filterXPath('//id'));
|
||||
$booking->bookingNumber = $this->getIntOrNullValue($node->filterXPath('//vorgangsnummer'));
|
||||
$booking->status = $this->getStringOrNullValue($node->filterXPath('//status'));
|
||||
$booking->participantCount = $this->getIntOrNullValue($node->filterXPath('//personen'));
|
||||
$booking->price = $this->stringToFloat($this->getStringOrNullValue($node->filterXPath('//preis')));
|
||||
$booking->bookingDate = $this
|
||||
->stringToDateTime($this->getStringOrNullValue($node->filterXPath('//buchungsdatum')));
|
||||
$booking->travel = $this->getStringOrNullValue($node->filterXPath('//reise'));
|
||||
$booking->travelId = $this->getIntOrNullValue($node->filterXPath('//idreise'));
|
||||
$booking->travelDate = $this
|
||||
->stringToDate($this->getStringOrNullValue($node->filterXPath('//reisedatum')));
|
||||
$booking->document = $this
|
||||
->stringToBool($this->getStringOrNullValue($node->filterXPath('//reisedokument')));
|
||||
$booking->payment = $this
|
||||
->stringToFloat($this->getStringOrNullValue($node->filterXPath('//zahlung')));
|
||||
|
||||
$bookings[] = $booking;
|
||||
});
|
||||
|
||||
return new BaseData($bookings);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\Country;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class CountriesParser
|
||||
{
|
||||
public function parse(Crawler $result): BaseData
|
||||
{
|
||||
$countries = [];
|
||||
|
||||
$result
|
||||
->filterXPath('//laender/land')
|
||||
->each(function (Crawler $node) use (&$countries) {
|
||||
$country = new Country();
|
||||
$country->id = (int) $node->attr('id');
|
||||
$country->name = $node->attr('bezeichnung');
|
||||
$country->token = $node->attr('kuerzel');
|
||||
$country->nationality = $node->attr('nationalitaet');
|
||||
|
||||
$countries[$country->token] = $country;
|
||||
})
|
||||
;
|
||||
|
||||
return new BaseData($countries);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\CrmAction;
|
||||
use App\BusProNet\Model\CrmAttributes;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
use App\BusProNet\Model\CrmSelectionGroup;
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class CrmAttributesResponseParser
|
||||
{
|
||||
use TypeConversionTrait;
|
||||
|
||||
private const BPN_CRM_ID_ADMIN = 1292;
|
||||
private const BPN_CRM_ID_MANAGER = 1293;
|
||||
private const BPN_CRM_ID_TEAMER = 1070;
|
||||
|
||||
public function parse(Crawler $result): CrmAttributes
|
||||
{
|
||||
$groups = [];
|
||||
$actions = [];
|
||||
$roles = [];
|
||||
$hotelCode = null;
|
||||
|
||||
$result
|
||||
->filterXPath('//selektionsmerkmale/selektionsgruppe')
|
||||
->each(function (Crawler $node) use (&$groups, &$roles, &$hotelCode) {
|
||||
$group = new CrmSelectionGroup();
|
||||
$group->id = (int) $node->attr('id');
|
||||
$group->label = $node->attr('bezeichnung');
|
||||
|
||||
$attributes = [];
|
||||
|
||||
$node
|
||||
->filterXPath('//selektion')
|
||||
->each(function (Crawler $node) use (&$attributes, &$roles, &$hotelCode) {
|
||||
$attribute = new CrmSelection();
|
||||
$attribute->id = (int) $node->attr('id');
|
||||
$attribute->label = $node->attr('bezeichnung');
|
||||
$attribute->mutable = $this->stringToBool($node->attr('aenderbar'));
|
||||
$attribute->selected = $this->stringToBool($node->attr('auswahl'));
|
||||
|
||||
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attribute->label, $matches) && true === $attribute->selected) {
|
||||
$roles[] = 'ROLE_HOUSE_MANAGER';
|
||||
$hotelCode = $matches[1];
|
||||
}
|
||||
if (static::BPN_CRM_ID_ADMIN === $attribute->id && true === $attribute->selected) {
|
||||
$roles[] = 'ROLE_ADMIN';
|
||||
}
|
||||
if (static::BPN_CRM_ID_MANAGER === $attribute->id && true === $attribute->selected) {
|
||||
$roles[] = 'ROLE_MANAGER';
|
||||
}
|
||||
if (static::BPN_CRM_ID_TEAMER === $attribute->id && true === $attribute->selected) {
|
||||
$roles[] = 'ROLE_TEAMER';
|
||||
}
|
||||
|
||||
$attributes[] = $attribute;
|
||||
})
|
||||
;
|
||||
|
||||
$group->selections = $attributes;
|
||||
$groups[] = $group;
|
||||
})
|
||||
;
|
||||
|
||||
$result
|
||||
->filterXPath('//crmaktionen/crmaktion')
|
||||
->each(function (Crawler $node) use (&$actions) {
|
||||
$crmAction = new CrmAction();
|
||||
|
||||
$crmAction->id = (int) $node->attr('id');
|
||||
$crmAction->code = $node->attr('code');
|
||||
$crmAction->label = $node->attr('bezeichnung');
|
||||
$crmAction->mutable = $this->stringToBool($node->attr('aenderbar'));
|
||||
$crmAction->selected = $this->stringToBool($node->attr('auswahl'));
|
||||
|
||||
$actions[] = $crmAction;
|
||||
})
|
||||
;
|
||||
|
||||
$response = new CrmAttributes();
|
||||
$response->selectionGroups = $groups;
|
||||
$response->crmActions = $actions;
|
||||
$response->roles = $roles;
|
||||
$response->admin = in_array('ROLE_ADMIN', $roles);
|
||||
$response->manager = in_array('ROLE_MANAGER', $roles);
|
||||
$response->houseManager = in_array('ROLE_HOUSE_MANAGER', $roles);
|
||||
$response->teamer = in_array('ROLE_TEAMER', $roles);
|
||||
$response->hotelCode = $hotelCode;
|
||||
|
||||
return $response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\File;
|
||||
use PhpZip\Exception\ZipException;
|
||||
use PhpZip\ZipFile;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class DocumentsParser
|
||||
{
|
||||
public function parseConfirmation(Crawler $result): ?File
|
||||
{
|
||||
$pdfData = $this->decode($result->filterXPath('//bestaetigungpdf'));
|
||||
|
||||
return new File('bestaetigung.pdf', $pdfData, 'application/pdf');
|
||||
}
|
||||
|
||||
public function parseDocuments(Crawler $result): ?File
|
||||
{
|
||||
$documents = $result->filterXPath('//reisedokumente/reisedokument');
|
||||
|
||||
if (1 === $documents->count()) {
|
||||
$node = $documents->first();
|
||||
[$filename, $pdfData] = $this->getFileInfo($node);
|
||||
|
||||
return new File($filename.'.pdf', $pdfData, 'application/pdf');
|
||||
}
|
||||
|
||||
// In case of multiple documents create ZIP file
|
||||
try {
|
||||
$zip = new ZipFile();
|
||||
|
||||
$documents->each(function (Crawler $node) use (&$zip) {
|
||||
[$filename, $pdfData] = $this->getFileInfo($node);
|
||||
$zip->addFromString($filename.'.pdf', $pdfData);
|
||||
});
|
||||
|
||||
return new File('reisedokumente.zip', $zip->outputAsString(), 'application/zip');
|
||||
}
|
||||
catch (ZipException $e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private function decode(Crawler $node): string
|
||||
{
|
||||
[, $pdfData] = explode(',', $node->text());
|
||||
|
||||
return base64_decode($pdfData);
|
||||
}
|
||||
|
||||
private function getFileInfo(Crawler $node): array
|
||||
{
|
||||
$pdfData = $this->decode($node->filterXPath('//pdf'));
|
||||
$filename = $node->filterXPath('//datei')->text();
|
||||
|
||||
return [$filename, $pdfData];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\MutableData;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class MutableDataParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): BaseData
|
||||
{
|
||||
$mutableFields = [];
|
||||
|
||||
$result
|
||||
->filterXPath('//änderungen/änderung')
|
||||
->each(function (Crawler $node) use (&$mutableFields) {
|
||||
$category = match ($node->attr('art')) {
|
||||
'anzahl_teilnehmer' => MutableData::CATEGORY_PARTICIPANT_COUNT,
|
||||
'beförderung' => MutableData::CATEGORY_TRANSPORTATION,
|
||||
'zustieg' => MutableData::CATEGORY_PICKUP,
|
||||
'unterbringung' => MutableData::CATEGORY_ACCOMMODATION,
|
||||
'zusatzleistung' => MutableData::CATEGORY_ADDITIONAL_SERVICES,
|
||||
'teilnehmerdaten' => MutableData::CATEGORY_PARTICIPANT_DATA,
|
||||
default => null,
|
||||
};
|
||||
|
||||
if (null !== $category) {
|
||||
$mutableField = new MutableData($category, $this->stringToBool($node->attr('möglich')));
|
||||
|
||||
if (null !== $until = $node->attr('möglichbiszum')) {
|
||||
$mutableField->mutableBefore = $this->stringToDate($until);
|
||||
}
|
||||
|
||||
$mutableFields[$category] = $mutableField;
|
||||
}
|
||||
})
|
||||
;
|
||||
|
||||
return new BaseData($mutableFields);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Notification;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class NotificationParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): Notification
|
||||
{
|
||||
$number = $this->getIntOrNullValue($result->filterXPath('//satz/nr'));
|
||||
$text = $this->getStringOrNullValue($result->filterXPath('//satz/text'));
|
||||
|
||||
return new Notification($number, $text);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Address;
|
||||
use App\BusProNet\Model\Communication;
|
||||
use App\BusProNet\Model\PersonalData;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use voku\helper\AntiXSS;
|
||||
|
||||
class PersonalDataParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $node): PersonalData
|
||||
{
|
||||
$personalData = new PersonalData();
|
||||
|
||||
$personalData->addressId = $this->getIntOrNullValue($node->filterXPath('//idadresse'));
|
||||
$personalData->personId = $this->getIntOrNullValue($node->filterXPath('//idperson'));
|
||||
|
||||
$addressDataNode = $node->filterXPath('//adressdaten');
|
||||
|
||||
$dateString = $this->getStringOrNullValue($addressDataNode->filterXPath('//geburtsdatum'));
|
||||
$personalData->dateOfBirth = null !== $dateString ?
|
||||
\DateTimeImmutable::createFromFormat('d.m.Y', $dateString) : null;
|
||||
|
||||
$personalData->firstName = $this->getStringOrNullValue($addressDataNode->filterXPath('//vorname'));
|
||||
$personalData->name = $this->getStringOrNullValue($addressDataNode->filterXPath('//name'));
|
||||
$personalData->salutation = $this->getStringOrNullValue($addressDataNode->filterXPath('//anrede'));
|
||||
$personalData->title = $this->getStringOrNullValue($addressDataNode->filterXPath('//titel'));
|
||||
$personalData->gender = strtoupper($this->getStringOrNullValue($addressDataNode->filterXPath('//geschlecht')));
|
||||
|
||||
$personalData->height = $this->getStringOrNullValue($addressDataNode->filterXPath('//sonstiges1'));
|
||||
$personalData->weight = $this->getStringOrNullValue($addressDataNode->filterXPath('//sonstiges2'));
|
||||
$personalData->shoeSize = $this->getStringOrNullValue($addressDataNode->filterXPath('//sonstiges3'));
|
||||
|
||||
$addressNode = $addressDataNode->filterXPath('//anschrift');
|
||||
|
||||
if (0 < $addressNode->count()) {
|
||||
$address = new Address();
|
||||
$address->street = $this->getStringOrNullValue($addressNode->filterXPath('//strasse'));
|
||||
$address->postCode = $this->getStringOrNullValue($addressNode->filterXPath('//plz'));
|
||||
$address->city = $this->getStringOrNullValue($addressNode->filterXPath('//ort')) ;
|
||||
$address->country = $this->getStringOrNullValue($addressNode->filterXPath('//land')) ;
|
||||
|
||||
$personalData->address = $address;
|
||||
}
|
||||
|
||||
$contactDataNode = $addressDataNode->filterXPath('//kommunikation');
|
||||
|
||||
if (0 < $contactDataNode->count()) {
|
||||
$communication = new Communication();
|
||||
$communication->phone = $this->getStringOrNullValue($contactDataNode->filterXPath('//telefonprivat'));
|
||||
$communication->mobile = $this->getStringOrNullValue($contactDataNode->filterXPath('//telefonmobil'));
|
||||
$communication->email = $this->getStringOrNullValue($contactDataNode->filterXPath('//email'));
|
||||
$communication->newsletter = $this
|
||||
->stringToBool($this->getStringOrNullValue($contactDataNode->filterXPath('//newsletter')));
|
||||
|
||||
$personalData->communication = $communication;
|
||||
}
|
||||
|
||||
$remarksNode = $addressDataNode->filterXPath('//bemerkung');
|
||||
|
||||
if (0 < $remarksNode->count()) {
|
||||
$antiXss = new AntiXSS();
|
||||
$personalData->remarks = $antiXss->xss_clean($remarksNode->text());
|
||||
}
|
||||
|
||||
return $personalData;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class PickupsParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): array
|
||||
{
|
||||
$pickups = [];
|
||||
|
||||
$result->each(function (Crawler $node) use (&$pickups) {
|
||||
$pickupId = (int) $node->attr('idzustieg');
|
||||
$pickupDate = $node->attr('datum');
|
||||
$pickupTime = $node->attr('zeit');
|
||||
$price = $node->attr('preis') ? $this->stringToFloat($node->attr('preis')) : null;
|
||||
|
||||
$pickup = new Pickup();
|
||||
$pickup->id = $pickupId;
|
||||
$pickup->code = $node->attr('code');
|
||||
$pickup->city = $this->getStringOrNullValue($node->filterXPath('//ort'));
|
||||
$pickup->postalCode = $this->getStringOrNullValue($node->filterXPath('//plz'));
|
||||
$pickup->street = $this->getStringOrNullValue($node->filterXPath('//strasse'));
|
||||
$pickup->time = $this->stringToDateTime($pickupDate.' '.$pickupTime);
|
||||
$pickup->price = $price;
|
||||
$mapping = $this->stringToArray($node->attr('zuordnung'));
|
||||
$pickup->mapping = array_map('intval', $mapping);
|
||||
|
||||
$pickups[$pickupId] = $pickup;
|
||||
});
|
||||
|
||||
return $pickups;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Room;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class RoomsParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): array
|
||||
{
|
||||
$rooms = [];
|
||||
|
||||
$result->each(function (Crawler $node) use (&$rooms) {
|
||||
$room = new Room();
|
||||
$room->id = (int) $node->attr('idzimmer');;
|
||||
$room->label = $node->attr('zimmer');
|
||||
$room->category = $node->attr('kategorie');
|
||||
$room->boardId = (int) $node->attr('idverpflegung');
|
||||
$room->dateFrom = $node->attr('anreise') ?
|
||||
$this->stringToDate($node->attr('anreise')) : null;
|
||||
$room->dateTo = $node->attr('abreise') ?
|
||||
$this->stringToDate($node->attr('abreise')) : null;
|
||||
$room->totalCount = (int) $node->attr('anzahl');
|
||||
$room->minPax = (int) $node->attr('minpax');
|
||||
$room->maxPax = (int) $node->attr('maxpax');
|
||||
$room->board = $node->attr('verpflegung');
|
||||
$mapping = $this->stringToArray($node->attr('zuordnung'));
|
||||
$room->mapping = array_map('intval', $mapping);
|
||||
$room->totalPrice = $this->stringToFloat($node->attr('gesamtpreis'));
|
||||
$individualPrices = array_map(
|
||||
function ($price) {
|
||||
return $this->stringToFloat($price);
|
||||
}, $this->stringToArray($node->attr('einzelpreis', ''), '/')
|
||||
);
|
||||
$room->individualPrice = array_combine($mapping, $individualPrices);
|
||||
|
||||
$rooms[$room->id] = $room;
|
||||
});
|
||||
|
||||
return $rooms;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Service;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class ServicesParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result, string $category, string $source): array
|
||||
{
|
||||
$services = [];
|
||||
|
||||
$result->each(function (Crawler $node) use (&$services, $category, $source) {
|
||||
$service = new Service();
|
||||
$service->id = (int) $node->attr('idleistung');
|
||||
$service->category = $category;
|
||||
$service->source = $source;
|
||||
$service->label = $node->attr('leistung');
|
||||
$service->dateFrom = $node->attr('termin') ?
|
||||
$this->stringToDate($node->attr('termin')) : null;
|
||||
$service->dateTo = $node->attr('terminbis') ?
|
||||
$this->stringToDate($node->attr('terminbis')) : null;
|
||||
$service->subType = $node->attr('unterart');
|
||||
$service->totalCount = $node->attr('anzahl') ? (int) $node->attr('anzahl') : null;
|
||||
$mapping = $this->stringToArray($node->attr('zuordnung'));
|
||||
$service->mapping = array_map('intval', $mapping);
|
||||
$service->totalPrice = $this->stringToFloat($node->attr('gesamtpreis'));
|
||||
$individualPrices = array_map(
|
||||
function ($price) {
|
||||
return $this->stringToFloat($price);
|
||||
}, $this->stringToArray($node->attr('einzelpreis', ''), '/')
|
||||
);
|
||||
$service->individualPrice = array_combine($mapping, $individualPrices);
|
||||
if (Service::CATEGORY_TRANSPORTATION === $category) {
|
||||
$service->direction = $node->attr('richtung');
|
||||
}
|
||||
|
||||
$services[$service->id] = $service;
|
||||
});
|
||||
|
||||
return $services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlParser;
|
||||
|
||||
use App\BusProNet\Model\Surcharge;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
|
||||
class SurchargesParser extends AbstractParser
|
||||
{
|
||||
public function parse(Crawler $result): array
|
||||
{
|
||||
$surcharges = [];
|
||||
|
||||
$result->each(function (Crawler $node) use (&$surcharges) {
|
||||
$surcharge = new Surcharge();
|
||||
$surchargeLabel = $node->attr('bezeichnung');
|
||||
$surcharge->label = empty($surchargeLabel) ? 'unbekannt' : $surchargeLabel;
|
||||
$surcharge->totalPrice = $this->stringToFloat($node->attr('gesamtpreis'));
|
||||
$mapping = $this->stringToArray($node->attr('zuordnung'));
|
||||
$surcharge->mapping = array_map('intval', $mapping);
|
||||
$individualPrices = array_map(
|
||||
function ($price) {
|
||||
return $this->stringToFloat($price);
|
||||
}, $this->stringToArray($node->attr('einzelpreis', ''), '/')
|
||||
);
|
||||
$surcharge->individualPrice = array_combine($mapping, $individualPrices);
|
||||
|
||||
$surcharges[] = $surcharge;
|
||||
});
|
||||
|
||||
return $surcharges;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user