272 lines
10 KiB
PHP
272 lines
10 KiB
PHP
<?php
|
|
|
|
namespace App\BusProNet;
|
|
|
|
use App\BusProNet\Model\Address;
|
|
use App\BusProNet\Model\BaseDataResponse;
|
|
use App\BusProNet\Model\Communication;
|
|
use App\BusProNet\Model\Country;
|
|
use App\BusProNet\Model\CrmAttribute;
|
|
use App\BusProNet\Model\CrmAttributeGroup;
|
|
use App\BusProNet\Model\CrmAttributesResponse;
|
|
use App\BusProNet\Model\Hotel;
|
|
use App\BusProNet\Model\NotificationResponse;
|
|
use App\BusProNet\Model\Pickup;
|
|
use App\BusProNet\Model\ProfileResponse;
|
|
use Symfony\Component\OptionsResolver\OptionsResolver;
|
|
|
|
class ResponseParser
|
|
{
|
|
private array $config;
|
|
|
|
public function __construct(array $options)
|
|
{
|
|
$this->config = $this->resolveOptions($options);
|
|
}
|
|
|
|
/**
|
|
* @throws ResponseParserException
|
|
*/
|
|
public function parseXmlString(string $type, string $content): mixed
|
|
{
|
|
$xml = simplexml_load_string($content);
|
|
|
|
// Override type when present in XML to catch error responses
|
|
$responseType = $type;
|
|
$responseTypeXml = $xml->xpath('satz/@typ');
|
|
if (0 < count($responseTypeXml)) {
|
|
$responseType = (string)$xml->xpath('satz/@typ')[0];
|
|
}
|
|
|
|
switch ($responseType) {
|
|
case ApiClient::TYPE_NOTIFICATION:
|
|
return $this->createNotificationResponse($xml);
|
|
case ApiClient::TYPE_CUSTOMER_DATA:
|
|
$subType = (string) $xml->xpath('art')[0];
|
|
switch ($subType) {
|
|
case 'Adressdaten':
|
|
case 'Adressdaten_Ändern':
|
|
return $this->createProfileResponse($xml);
|
|
case 'SelektionCRM':
|
|
case 'SelektionCRM_Ändern':
|
|
return $this->createCrmAttributesResponse($xml);
|
|
}
|
|
break;
|
|
case ApiClient::TYPE_BASE_DATA_COUNTRIES:
|
|
return $this->createCountriesResponse($xml);
|
|
case ApiClient::TYPE_BASE_DATA_PICKUPS:
|
|
return $this->createPickupsResponse($xml);
|
|
case ApiClient::TYPE_BASE_DATA_HOTELS:
|
|
return $this->createHotelsResponse($xml);
|
|
}
|
|
|
|
throw new ResponseParserException('Unable to parse XML response');
|
|
}
|
|
|
|
public function createNotificationResponse(\SimpleXMLElement $xml): NotificationResponse
|
|
{
|
|
$code = (int) $xml->xpath('satz/nr')[0];
|
|
$message = (string) $xml->xpath('satz/text')[0];
|
|
|
|
return new NotificationResponse($code, $message);
|
|
}
|
|
|
|
public function createProfileResponse(\SimpleXMLElement $xml): ProfileResponse
|
|
{
|
|
$addressId = (int) $xml->xpath('idadresse')[0];
|
|
$personId = (int) $xml->xpath('idperson')[0];
|
|
|
|
$lastName = (string) $xml->xpath('adressdaten/name')[0];
|
|
$firstName = (string) $xml->xpath('adressdaten/vorname')[0];
|
|
$salutation = (string) $xml->xpath('adressdaten/anrede')[0];
|
|
$title = (string) $xml->xpath('adressdaten/titel')[0];
|
|
|
|
$gender = (string) $xml->xpath('adressdaten/geschlecht')[0];
|
|
$gender = strtoupper($gender) === 'W' ? 'F' : strtoupper($gender);
|
|
|
|
$date = $xml->xpath('adressdaten/geburtsdatum');
|
|
$dateOfBirth = $date ?\DateTimeImmutable::createFromFormat('d.m.Y', (string) $date[0]) : null;
|
|
|
|
$response = new ProfileResponse();
|
|
$response
|
|
->setAddressId($addressId)
|
|
->setPersonId($personId)
|
|
->setFirstName($firstName)
|
|
->setName($lastName)
|
|
->setTitle($title)
|
|
->setSalutation($salutation)
|
|
->setGender($gender)
|
|
->setDateOfBirth($dateOfBirth)
|
|
;
|
|
|
|
$postalAddressStreet = $xml->xpath('adressdaten/anschrift/strasse');
|
|
$postalAddressPostcode = $xml->xpath('adressdaten/anschrift/plz');
|
|
$postalAddressCity = $xml->xpath('adressdaten/anschrift/ort');
|
|
$postalAddressCountry = $xml->xpath('adressdaten/anschrift/land');
|
|
|
|
$address = new Address();
|
|
$address
|
|
->setStreet($postalAddressStreet ? (string) $postalAddressStreet[0] : null)
|
|
->setPostCode($postalAddressPostcode ? (string) $postalAddressPostcode[0] : null)
|
|
->setCity($postalAddressCity ? (string) $postalAddressCity[0] : null)
|
|
->setCountry($postalAddressCountry ? (string) $postalAddressCountry[0] : null)
|
|
;
|
|
|
|
$response->setAddress($address);
|
|
|
|
$phone = $xml->xpath('adressdaten/kommunikation/telefonprivat');
|
|
$mobile = $xml->xpath('adressdaten/kommunikation/telefonmobil');
|
|
$email = $xml->xpath('adressdaten/kommunikation/email');
|
|
|
|
$communication = new Communication();
|
|
$communication
|
|
->setPhone($phone ? (string) $phone[0] : null)
|
|
->setMobile($mobile ? (string) $mobile[0] : null)
|
|
->setEmail($email ? (string) $email[0] : null)
|
|
;
|
|
|
|
$response->setCommunication($communication);
|
|
|
|
return $response;
|
|
}
|
|
|
|
public function createCrmAttributesResponse(\SimpleXMLElement $xml): CrmAttributesResponse
|
|
{
|
|
$groups = [];
|
|
$isAdmin = $isManager = $isHouseManager = $isTeamer = false;
|
|
$hotelCode = null;
|
|
|
|
foreach ($xml->xpath('selektionsmerkmale/selektionsgruppe') as $item) {
|
|
$group = new CrmAttributeGroup();
|
|
$group->setLabel($item->attributes()['bezeichnung']);
|
|
$attributes = [];
|
|
|
|
foreach ($item->xpath('selektion') as $subItem) {
|
|
$attributeId = (int) $subItem->attributes()['id'];
|
|
$attributeLabel = (string) $subItem->attributes()['bezeichnung'];
|
|
$attributeSelected = 'True' === (string) $subItem->attributes()['auswahl'];
|
|
$attribute = new CrmAttribute();
|
|
$attribute
|
|
->setId($attributeId)
|
|
->setLabel($attributeLabel)
|
|
->setSelected($attributeSelected)
|
|
;
|
|
$attributes[] = $attribute;
|
|
|
|
if (1 === preg_match('/^Hausleitung ([A-Z0-9]+)$/', $attributeLabel, $matches) && true === $attributeSelected) {
|
|
$isHouseManager = true;
|
|
$hotelCode = $matches[1];
|
|
}
|
|
if ($this->config['bpn_crm_id_admin'] === $attribute->getId() && true === $attribute->isSelected()) {
|
|
$isAdmin = true;
|
|
}
|
|
if ($this->config['bpn_crm_id_manager'] === $attribute->getId() && true === $attribute->isSelected()) {
|
|
$isManager = true;
|
|
}
|
|
if ($this->config['bpn_crm_id_teamer'] === $attribute->getId() && true === $attribute->isSelected()) {
|
|
$isTeamer = true;
|
|
}
|
|
}
|
|
$group->setAttributes($attributes);
|
|
$groups[] = $group;
|
|
}
|
|
|
|
// Apply additional role and hotel code for testing purposes when provided
|
|
if ($isAdmin && null !== $this->config['bpn_default_hotel_code']) {
|
|
$isHouseManager = true;
|
|
$hotelCode = $this->config['bpn_default_hotel_code'];
|
|
}
|
|
|
|
$response = new CrmAttributesResponse();
|
|
$response
|
|
->setAttributeGroups($groups)
|
|
->setAdmin($isAdmin)
|
|
->setManager($isManager)
|
|
->setTeamer($isTeamer)
|
|
->setHouseManager($isHouseManager)
|
|
->setHotelCode($hotelCode)
|
|
;
|
|
|
|
return $response;
|
|
}
|
|
|
|
public function createCountriesResponse(\SimpleXMLElement $xml): BaseDataResponse
|
|
{
|
|
$countries = [];
|
|
|
|
foreach ($xml->xpath('laender/land') as $item) {
|
|
$token = (string) $item->attributes()['kuerzel'];
|
|
$country = new Country();
|
|
$country
|
|
->setId((int) $item->attributes()['id'])
|
|
->setName((string) $item->attributes()['bezeichnung'])
|
|
->setToken((string) $item->attributes()['kuerzel'])
|
|
->setNationality((string) $item->attributes()['nationalitaet'])
|
|
;
|
|
$countries[$token] = $country;
|
|
}
|
|
|
|
return new BaseDataResponse($countries);
|
|
}
|
|
|
|
public function createPickupsResponse(\SimpleXMLElement $xml): BaseDataResponse
|
|
{
|
|
$pickups = [];
|
|
|
|
foreach ($xml->xpath('zustieg') as $item) {
|
|
$id = (int) $item->attributes()['id'];
|
|
$busProId = (int) $item->attributes()['idbuspro'];
|
|
$pickup = new Pickup();
|
|
$pickup
|
|
->setId($id)
|
|
->setBusProId($busProId)
|
|
->setCode((string) $item->attributes()['code'])
|
|
->setCity($item->xpath('ort') ? (string) $item->xpath('ort')[0] : null)
|
|
->setStreet($item->xpath('strasse') ? (string) $item->xpath('strasse')[0] : '')
|
|
;
|
|
$pickups[$busProId] = $pickup;
|
|
}
|
|
|
|
return new BaseDataResponse($pickups);
|
|
}
|
|
|
|
public function createHotelsResponse(\SimpleXMLElement $xml): BaseDataResponse
|
|
{
|
|
$hotels = [];
|
|
|
|
foreach ($xml->xpath('hotel') as $item) {
|
|
$id = (int) $item->attributes()['id'];
|
|
$busProId = (int) $item->attributes()['idbuspro'];
|
|
$hotel = new Hotel();
|
|
$hotel
|
|
->setId($id)
|
|
->setBusProId($busProId)
|
|
->setCode((string) $item->attributes()['code'])
|
|
->setName($item->xpath('name') ? (string) $item->xpath('name')[0] : null)
|
|
->setCountry($item->xpath('land') ? strtolower((string) $item->xpath('land')[0]) : null)
|
|
->setCity($item->xpath('ort') ? (string) $item->xpath('ort')[0] : null)
|
|
->setStreet($item->xpath('strasse') ? (string) $item->xpath('strasse')[0] : null)
|
|
->setPhone($item->xpath('telefon') ? (string) $item->xpath('telefon')[0] : null)
|
|
->setType($item->xpath('art') ? (string) $item->xpath('art')[0] : null)
|
|
;
|
|
$hotels[$busProId] = $hotel;
|
|
}
|
|
|
|
return new BaseDataResponse($hotels);
|
|
}
|
|
|
|
private function resolveOptions(array $options): array
|
|
{
|
|
$optionsResolver = new OptionsResolver();
|
|
$optionsResolver->setRequired(['bpn_crm_id_admin', 'bpn_crm_id_manager', 'bpn_crm_id_teamer']);
|
|
$optionsResolver->setDefaults([
|
|
'bpn_default_hotel_code' => null,
|
|
]);
|
|
$optionsResolver->setAllowedTypes('bpn_crm_id_admin', 'int');
|
|
$optionsResolver->setAllowedTypes('bpn_crm_id_manager', 'int');
|
|
$optionsResolver->setAllowedTypes('bpn_crm_id_teamer', 'int');
|
|
$optionsResolver->setAllowedTypes('bpn_default_hotel_code', ['string', 'null']);
|
|
|
|
return $optionsResolver->resolve($options);
|
|
}
|
|
} |