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); } }