feat: refactoring of xml parsers
This commit is contained in:
1 parent
11f1508640
commit
6730c243f6
49 files changed
+1414
-1235
No files matched your search
+3
-1
@@ -3,11 +3,13 @@
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\TypeConversionTrait;
|
||||
use App\BusProNet\XmlParserTrait;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
|
||||
abstract class AbstractXmlLoader
|
||||
abstract class AbstractLoader
|
||||
{
|
||||
use TypeConversionTrait;
|
||||
use XmlParserTrait;
|
||||
|
||||
public function __construct(protected readonly CacheInterface $cache, protected readonly ?string $xmlPath = null)
|
||||
{
|
||||
+22
-20
@@ -5,24 +5,27 @@ namespace App\BusProNet\XmlLoader;
|
||||
use App\BusProNet\Model\Hotel;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class HotelXmlLoader extends AbstractXmlLoader
|
||||
class HotelLoader extends AbstractLoader
|
||||
{
|
||||
public function loadAll(?string $filename = 'hotel.xml'): array
|
||||
{
|
||||
try {
|
||||
return $this->cache->get('bpn_hotels', function (ItemInterface $item) use ($filename) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
$xml = $this->loadXml($filename);
|
||||
$item->expiresAfter(3 * 60 * 60);
|
||||
|
||||
$hotels = [];
|
||||
|
||||
foreach ($xml->hotel as $hotel) {
|
||||
$id = (int)$hotel->attributes()['idbuspro'];
|
||||
$hotels[$id] = $this->parseXml($hotel);
|
||||
}
|
||||
$this
|
||||
->loadXml($filename)
|
||||
->filterXPath('//hotels/hotel')
|
||||
->each(function (Crawler $node) use (&$hotels) {
|
||||
$id = (int) $node->attr('idbuspro');
|
||||
$hotels[$id] = $this->parseXml($node);
|
||||
})
|
||||
;
|
||||
|
||||
return $hotels;
|
||||
});
|
||||
@@ -51,25 +54,24 @@ class HotelXmlLoader extends AbstractXmlLoader
|
||||
return $hotels[$id] ?? null;
|
||||
}
|
||||
|
||||
private function loadXml(?string $filename = 'hotel.xml'): \SimpleXMLElement
|
||||
private function loadXml(?string $filename = 'hotel.xml'): Crawler
|
||||
{
|
||||
$filepath = $this->xmlPath.'/'.$filename;
|
||||
$xml = file_get_contents($filepath);
|
||||
|
||||
return simplexml_load_file($filepath);
|
||||
return new Crawler($xml);
|
||||
}
|
||||
|
||||
public function parseXml(\SimpleXMLElement $xml): Hotel
|
||||
public function parseXml(Crawler $node): Hotel
|
||||
{
|
||||
$attributes = $xml->attributes();
|
||||
|
||||
$hotel = new Hotel();
|
||||
$hotel->id = (int) $attributes['idbuspro'];
|
||||
$hotel->code = (string) $attributes['code'];
|
||||
$hotel->name = (string) $xml->name;
|
||||
$hotel->city = $xml->ort ? (string) $xml->ort : null;
|
||||
$hotel->country = (string) $xml->land;
|
||||
$hotel->street = (string) $xml->strasse;
|
||||
$hotel->phone = $xml->telefon ? (string) $xml->telefon : null;
|
||||
$hotel->id = (int) $node->attr('idbuspro');
|
||||
$hotel->code = $node->attr('code');
|
||||
$hotel->name = $this->getStringOrNullValue($node->filterXPath('//name'));
|
||||
$hotel->city = $this->getStringOrNullValue($node->filterXPath('//ort'));
|
||||
$hotel->country = $this->getStringOrNullValue($node->filterXPath('//land'));
|
||||
$hotel->street = $this->getStringOrNullValue($node->filterXPath('//strasse'));
|
||||
$hotel->phone = $this->getStringOrNullValue($node->filterXPath('//telefon'));
|
||||
|
||||
return $hotel;
|
||||
}
|
||||
+15
-15
@@ -5,24 +5,26 @@ namespace App\BusProNet\XmlLoader;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class PickupXmlLoader extends AbstractXmlLoader
|
||||
class PickupLoader extends AbstractLoader
|
||||
{
|
||||
public function loadAll(?string $filename = 'zustiege.xml'): array
|
||||
{
|
||||
try {
|
||||
return $this->cache->get('bpn_pickups', function (ItemInterface $item) use ($filename) {
|
||||
$item->expiresAfter(3600);
|
||||
$item->expiresAfter(3 * 60 * 60);
|
||||
|
||||
$xml = simplexml_load_file($this->xmlPath . '/' . $filename);
|
||||
$crawler = new Crawler(file_get_contents($this->xmlPath . '/' . $filename));
|
||||
$pickupNodes = $crawler->filterXPath('//zustiege/zustieg');
|
||||
|
||||
$pickups = [];
|
||||
|
||||
foreach ($xml->zustieg as $pickup) {
|
||||
$id = (int)$pickup->attributes()['idbuspro'];
|
||||
$pickups[$id] = $this->parseXml($pickup);
|
||||
}
|
||||
$pickupNodes->each(function (Crawler $node) use (&$pickups) {
|
||||
$id = $node->attr('idbuspro');
|
||||
$pickups[$id] = $this->parseXml($node);
|
||||
});
|
||||
|
||||
return $pickups;
|
||||
});
|
||||
@@ -38,16 +40,14 @@ class PickupXmlLoader extends AbstractXmlLoader
|
||||
return $pickups[$id] ?? null;
|
||||
}
|
||||
|
||||
public function parseXml(\SimpleXMLElement $xml): Pickup
|
||||
public function parseXml(Crawler $node): Pickup
|
||||
{
|
||||
$attributes = $xml->attributes();
|
||||
|
||||
$pickup = new Pickup();
|
||||
$pickup->id = (int) $attributes['idbuspro'];
|
||||
$pickup->code = (string) $attributes['code'];
|
||||
$pickup->city = (string) $xml->ort;
|
||||
$pickup->postalCode = (string) $xml->plz;
|
||||
$pickup->street = (string) $xml->strasse;
|
||||
$pickup->id = (int) $node->attr('idbuspro');
|
||||
$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'));
|
||||
|
||||
return $pickup;
|
||||
}
|
||||
@@ -0,0 +1,350 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
use App\BusProNet\Model\CrmSelectionGroup;
|
||||
use App\BusProNet\Model\Guide;
|
||||
use App\BusProNet\Model\MutableData;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Room;
|
||||
use App\BusProNet\Model\Service;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use Psr\Cache\InvalidArgumentException;
|
||||
use Symfony\Component\DomCrawler\Crawler;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class TravelLoader extends AbstractLoader
|
||||
{
|
||||
public function __construct(
|
||||
private readonly HotelLoader $hotelDataLoader,
|
||||
CacheInterface $cache,
|
||||
?string $xmlPath = null
|
||||
) {
|
||||
parent::__construct($cache, $xmlPath);
|
||||
}
|
||||
|
||||
public function generateFilesMap(): array
|
||||
{
|
||||
try {
|
||||
return $this->cache->get('bpn_travels_mapping', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3 * 60 * 60);
|
||||
|
||||
$finder = new Finder();
|
||||
$finder->files()->in($this->xmlPath)->name('Ziel_*.xml');
|
||||
|
||||
$mapping = [];
|
||||
$hotels = $this->hotelDataLoader->loadAll();
|
||||
|
||||
foreach ($finder as $file) {
|
||||
$xml = $file->getContents();
|
||||
$crawler = new Crawler($xml);
|
||||
$travelDataNodes = $crawler->filterXPath('//reisen/reise/termin');
|
||||
|
||||
$travelDataNodes->each(function (Crawler $node) use (&$mapping, $hotels, $file) {
|
||||
$travelId = $node->attr('idbuspro');
|
||||
|
||||
$mapping[$travelId] = [
|
||||
'id' => $travelId,
|
||||
'code' => $node->attr('code'),
|
||||
'label' => $this->getStringOrNullValue($node->filterXPath('//text')),
|
||||
'dateFrom' => $this->stringToDate($node->attr('termin')),
|
||||
'dateTo' => $this->stringToDate($node->attr('bis')),
|
||||
'hotels' => [],
|
||||
'file' => $file->getRealPath(),
|
||||
];
|
||||
|
||||
$node->filterXPath('//hotel')
|
||||
->each(function (Crawler $hotelNode) use (&$mapping, $hotels, $travelId) {
|
||||
$hotelId = (int) $hotelNode->attr('idbuspro');
|
||||
|
||||
$mapping[$travelId]['hotels'][$hotelId] = [
|
||||
'id' => $hotelId,
|
||||
'code' => $hotelNode->attr('code'),
|
||||
'label' => $hotels[$hotelId]->name,
|
||||
];
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
});
|
||||
} catch (InvalidArgumentException $e) {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
|
||||
public function mapCodeToId(string $travelCode): ?int
|
||||
{
|
||||
$mapping = $this->generateFilesMap();
|
||||
|
||||
$travelCodes = array_column($mapping, 'code', 'id');
|
||||
|
||||
if (false === $travelId = array_search($travelCode, $travelCodes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $travelId;
|
||||
}
|
||||
|
||||
public function loadById(int $travelId, ?int $hotelId = null, ?string $filename = null): ?Travel
|
||||
{
|
||||
if (null !== $filename) {
|
||||
return $this->loadXml($travelId, $hotelId, $filename);
|
||||
}
|
||||
|
||||
$mapping = $this->generateFilesMap();
|
||||
|
||||
if (false === isset($mapping[$travelId])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$filename = $mapping[$travelId]['file'];
|
||||
|
||||
return $this->loadXml($travelId, $hotelId, $filename);
|
||||
}
|
||||
|
||||
private function loadXml(int $id, ?int $hotelId, string $filename): ?Travel
|
||||
{
|
||||
$xml = file_get_contents($filename);
|
||||
$crawler = new Crawler($xml);
|
||||
|
||||
$travelNode = $crawler->filterXPath(sprintf('//reise/termin[@idbuspro="%d"]', $id));
|
||||
|
||||
if (0 === $travelNode->count()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->parseXml($travelNode->first(), $hotelId);
|
||||
}
|
||||
|
||||
public function parseXml(Crawler $node, ?int $hotelId): Travel
|
||||
{
|
||||
$hotelNode = $this->getHotelNode($node, $hotelId);
|
||||
|
||||
$travel = new Travel();
|
||||
$travel->id = (int) $node->attr('idbuspro');
|
||||
$travel->hotelId = $hotelId;
|
||||
$travel->label = $this->getStringOrNullValue($node->filterXPath('//text'));
|
||||
$travel->dateFrom = $this->stringToDate($node->attr('termin'));
|
||||
$travel->dateTo = $this->stringToDate($node->attr('bis'));
|
||||
$travel->code = $node->attr('code');
|
||||
$travel->type = $node->attr('reiseart');
|
||||
$travel->priceFrom = $this->stringToFloat($this->getStringOrNullValue($node->filterXPath('//abpreis')));
|
||||
$travel->selectionGroups = $this->getSelectionGroups($node->filterXPath('//selektionsgruppe'));
|
||||
$travel->additionalServices = $this
|
||||
->getAdditionalServices($node->filterXPath('//lei_sonstiges/leistung'));
|
||||
$travel->transportationServices = $this
|
||||
->getTransportationServices($node->filterXPath('//lei_befoerderung/leistung'));
|
||||
$travel->rooms = $this->getRooms($hotelNode);
|
||||
$travel->pickups = $this->getPickups($node->filterXPath('//zustiege/zustieg'));
|
||||
|
||||
return $travel;
|
||||
}
|
||||
|
||||
public function getSelectionGroups(Crawler $node): array
|
||||
{
|
||||
$selectionGroups = [];
|
||||
|
||||
$node->each(function (Crawler $groupNode) use (&$selectionGroups) {
|
||||
$groupId = (int) $groupNode->attr('idbuspro');
|
||||
$selectionGroup = new CrmSelectionGroup();
|
||||
$selectionGroup->id = $groupId;
|
||||
$selectionGroup->label = $groupNode->attr('bezeichnung');
|
||||
|
||||
$groupNode
|
||||
->filterXPath('//selektion')
|
||||
->each(function (Crawler $selectionNode) use (&$selectionGroups, &$selectionGroup, $groupId) {
|
||||
$selectionId = (int) $selectionNode->attr('idbuspro');
|
||||
$selection = new CrmSelection();
|
||||
$selection->id = $selectionId;
|
||||
$selection->label = $selectionNode->attr('bezeichnung');
|
||||
$selectionGroups[$groupId]['selections'][$selectionId] = $selectionNode->attr('bezeichnung');
|
||||
$selectionGroup->selections[] = $selection;
|
||||
})
|
||||
;
|
||||
|
||||
$selectionGroups[$groupId] = $selectionGroup;
|
||||
});
|
||||
|
||||
return $selectionGroups;
|
||||
}
|
||||
|
||||
public function getAdditionalServices(Crawler $node): array
|
||||
{
|
||||
$additionalServices = [];
|
||||
|
||||
$node->each(function (Crawler $serviceNode) use (&$additionalServices) {
|
||||
$serviceId = (int) $serviceNode->attr('idbuspro');
|
||||
|
||||
$service = new Service();
|
||||
$service->source = Service::SOURCE_TRAVEL;
|
||||
$service->category = Service::CATEGORY_ADDITIONAL;
|
||||
$service->id = $serviceId;
|
||||
$service->subType = $serviceNode->attr('unterart');
|
||||
$service->mandatory = $this->stringToBool($serviceNode->attr('pflicht'));
|
||||
$service->dateFrom = $this->stringToDate($serviceNode->attr('termin'));
|
||||
$service->dateTo = $this->stringToDate($serviceNode->attr('bis'));
|
||||
$service->label = $this->getStringOrNullValue($serviceNode->filterXPath('//text'));
|
||||
$service->price = $this
|
||||
->stringToFloat($this->getStringOrNullValue($serviceNode->filterXPath('//preis')));
|
||||
$service->status = $this->getStringOrNullValue($serviceNode->filterXPath('//status'));
|
||||
|
||||
$additionalServices[$serviceId] = $service;
|
||||
});
|
||||
|
||||
return $additionalServices;
|
||||
}
|
||||
|
||||
public function getGuideForTransportationService(\SimpleXMLElement $xmlTransportationService): ?Guide
|
||||
{
|
||||
if (null === $xmlTransportationService->reiseleiter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$guide = new Guide();
|
||||
$guide->name = $xmlTransportationService->reiseleiter->name;
|
||||
$guide->phone = $xmlTransportationService->reiseleiter->telefon;
|
||||
|
||||
return $guide;
|
||||
}
|
||||
|
||||
public function getTransportationServices(Crawler $node): array
|
||||
{
|
||||
$transportationServices = [];
|
||||
|
||||
$node->each(function (Crawler $serviceNode) use (&$transportationServices) {
|
||||
$serviceId = (int) $serviceNode->attr('idbuspro');
|
||||
|
||||
$service = new Service();
|
||||
$service->source = Service::SOURCE_TRAVEL;
|
||||
$service->category = Service::CATEGORY_TRANSPORTATION;
|
||||
$service->id = $serviceId;
|
||||
$service->subType = $serviceNode->attr('unterart');
|
||||
$service->dateFrom = $this->stringToDate($serviceNode->attr('termin'));
|
||||
$service->dateTo = $this->stringToDate($serviceNode->attr('bis'));
|
||||
$service->label = $this->getStringOrNullValue($serviceNode->filterXPath('//text'));
|
||||
$service->direction = $this->getStringOrNullValue($serviceNode->filterXPath('//richtung'));
|
||||
|
||||
$transportationServices[$serviceId] = $service;
|
||||
});
|
||||
|
||||
return $transportationServices;
|
||||
}
|
||||
|
||||
public function getPickups(Crawler $node): array
|
||||
{
|
||||
$pickups = [];
|
||||
|
||||
$node->each(function (Crawler $pickupNode) use (&$pickups) {
|
||||
$pickupId = (int) $pickupNode->attr('idbuspro');
|
||||
|
||||
$pickup = new Pickup();
|
||||
$pickup->id = $pickupId;
|
||||
$pickup->time = $this->stringToDateTime($pickupNode->attr('zeit'));
|
||||
$pickup->price = $pickupNode->attr('preis') ?
|
||||
$this->stringToFloat($pickupNode->attr('preis')) : null;
|
||||
|
||||
$pickups[$pickupId] = $pickup;
|
||||
});
|
||||
|
||||
return $pickups;
|
||||
}
|
||||
|
||||
public function getHotelNode(Crawler $node, ?int $hotelId): Crawler
|
||||
{
|
||||
// In case not hotel id is provided, take the first hotel node (which is most probably the only one)
|
||||
if (null === $hotelId) {
|
||||
return $node->filterXPath('//hotel')->first();
|
||||
}
|
||||
|
||||
$hotelNode = $node->filterXPath(sprintf('//hotel[@idbuspro="%d"]', $hotelId));
|
||||
|
||||
return $hotelNode->first();
|
||||
}
|
||||
|
||||
public function getRooms(Crawler $node): array
|
||||
{
|
||||
$roomNodes = $node->filterXPath('//zimmer/preis');
|
||||
|
||||
if (0 === $roomNodes->count()) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$rooms = [];
|
||||
|
||||
$roomNodes->each(function (Crawler $roomNode) use (&$rooms) {
|
||||
$roomId = (int) $roomNode->attr('idbuspro_zimmer');
|
||||
|
||||
$room = new Room();
|
||||
$room->id = $roomId;
|
||||
$room->code = $roomNode->attr('zimmercode');
|
||||
$room->category = $roomNode->attr('kat');
|
||||
$room->boardId = (int) $roomNode->attr('idbuspro_vp');
|
||||
$room->label = $roomNode->attr('zimmertext');
|
||||
$room->minPax = (int) $roomNode->attr('MinPax');
|
||||
$room->maxPax = (int) $roomNode->attr('MaxPax');
|
||||
$room->nights = (int) $roomNode->attr('naechte');
|
||||
$room->price = $roomNode->attr('preis') ?
|
||||
$this->stringToFloat($roomNode->attr('preis')) : null;
|
||||
$room->status = $this->getStringOrNullValue($roomNode->filterXPath('//status'));
|
||||
$room->available = (int) $roomNode->attr('verfuegbar');
|
||||
|
||||
$rooms[$roomId] = $room;
|
||||
});
|
||||
|
||||
return $rooms;
|
||||
}
|
||||
|
||||
public function patchMutability(Travel $travel, BaseData $mutableData): void
|
||||
{
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_ADDITIONAL_SERVICES)) {
|
||||
$travel->additionalServicesMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_TRANSPORTATION)) {
|
||||
$travel->transportationServicesMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PICKUP)) {
|
||||
$travel->pickupsMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_ACCOMMODATION)) {
|
||||
$travel->roomsMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PARTICIPANT_COUNT)) {
|
||||
$travel->participantCountMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PARTICIPANT_DATA)) {
|
||||
$travel->participantDataMutable = $item->mutable;
|
||||
}
|
||||
}
|
||||
|
||||
public function patchAvailabilities(Travel $travel, BaseData $availabilities): void
|
||||
{
|
||||
$serviceAvailabilities = $availabilities->getItems();
|
||||
|
||||
foreach ([...$travel->additionalServices, ...$travel->transportationServices] as $service) {
|
||||
if (array_key_exists($service->id, $serviceAvailabilities)) {
|
||||
$service->available = $serviceAvailabilities[$service->id]->available;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function patchBookings(BaseData $bookings): void
|
||||
{
|
||||
foreach ($bookings->getItems() as $booking) {
|
||||
if (null === $travelId = $booking->travelId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$booking->travelData = $this->loadById($travelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,338 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\BusProNet\XmlLoader;
|
||||
|
||||
use App\BusProNet\Model\BaseData;
|
||||
use App\BusProNet\Model\CrmSelection;
|
||||
use App\BusProNet\Model\CrmSelectionGroup;
|
||||
use App\BusProNet\Model\Guide;
|
||||
use App\BusProNet\Model\MutableData;
|
||||
use App\BusProNet\Model\Pickup;
|
||||
use App\BusProNet\Model\Room;
|
||||
use App\BusProNet\Model\Service;
|
||||
use App\BusProNet\Model\Travel;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Contracts\Cache\CacheInterface;
|
||||
use Symfony\Contracts\Cache\ItemInterface;
|
||||
|
||||
class TravelXmlLoader extends AbstractXmlLoader
|
||||
{
|
||||
public function __construct(
|
||||
private readonly HotelXmlLoader $hotelDataLoader,
|
||||
CacheInterface $cache,
|
||||
?string $xmlPath = null
|
||||
) {
|
||||
parent::__construct($cache, $xmlPath);
|
||||
}
|
||||
|
||||
public function generateFilesMap(): array
|
||||
{
|
||||
return $this->cache->get('bpn_travels_mapping', function (ItemInterface $item) {
|
||||
$item->expiresAfter(3600);
|
||||
|
||||
$finder = new Finder();
|
||||
$finder->files()->in($this->xmlPath)->name('Ziel_*.xml');
|
||||
|
||||
$mapping = [];
|
||||
$hotels = $this->hotelDataLoader->loadAll();
|
||||
|
||||
foreach ($finder as $file) {
|
||||
$xml = simplexml_load_file($file->getRealPath());
|
||||
|
||||
foreach ($xml->reise->termin as $travelXml) {
|
||||
$attributes = $travelXml->attributes();
|
||||
|
||||
$travelId = (int) $attributes['idbuspro'];
|
||||
|
||||
$mapping[$travelId] = [
|
||||
'id' => (int) $attributes['idbuspro'],
|
||||
'code' => (string) $attributes['code'],
|
||||
'label' => (string) $travelXml->text,
|
||||
'dateFrom' => $this->stringToDate((string) $attributes['termin']),
|
||||
'dateTo' => $this->stringToDate((string) $attributes['bis']),
|
||||
'hotels' => [],
|
||||
'file' => $file->getRealPath(),
|
||||
];
|
||||
|
||||
foreach ($travelXml->hotel as $hotelXml) {
|
||||
$hotelId = (int) $hotelXml->attributes()['idbuspro'];
|
||||
|
||||
$mapping[$travelId]['hotels'][$hotelId] = [
|
||||
'id' => $hotelId,
|
||||
'code' => (string) $hotelXml->attributes()['code'],
|
||||
'label' => $hotels[$hotelId]->name,
|
||||
];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $mapping;
|
||||
});
|
||||
}
|
||||
|
||||
public function mapCodeToId(string $travelCode): ?int
|
||||
{
|
||||
$mapping = $this->generateFilesMap();
|
||||
|
||||
$travelCodes = array_column($mapping, 'code', 'id');
|
||||
|
||||
if (false === $travelId = array_search($travelCode, $travelCodes)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $travelId;
|
||||
}
|
||||
|
||||
public function loadById(int $travelId, ?int $hotelId = null, ?string $filename = null): ?Travel
|
||||
{
|
||||
if (null !== $filename) {
|
||||
return $this->loadXml($travelId, $hotelId, $filename);
|
||||
}
|
||||
|
||||
$mapping = $this->generateFilesMap();
|
||||
|
||||
if (false === isset($mapping[$travelId])) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$filename = $mapping[$travelId]['file'];
|
||||
|
||||
return $this->loadXml($travelId, $hotelId, $filename);
|
||||
}
|
||||
|
||||
private function loadXml(int $id, ?int $hotelId, string $filename): ?Travel
|
||||
{
|
||||
$xml = simplexml_load_file($filename);
|
||||
|
||||
$travelXml = $xml->xpath(sprintf('//reise/termin[@idbuspro="%d"]', $id));
|
||||
|
||||
if (0 === count($travelXml)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $this->parseXml($travelXml[0], $hotelId);
|
||||
}
|
||||
|
||||
public function parseXml(\SimpleXMLElement $xml, ?int $hotelId): Travel
|
||||
{
|
||||
$attributes = $xml->attributes();
|
||||
$hotelXml = $this->getHotelXml($xml, $hotelId);
|
||||
|
||||
$travel = new Travel();
|
||||
$travel->id = (int) $attributes['idbuspro'];
|
||||
$travel->hotelId = $hotelId;
|
||||
$travel->label = (string) $xml->text;
|
||||
$travel->dateFrom = $this->stringToDate((string) $attributes['termin']);
|
||||
$travel->dateTo = $this->stringToDate((string) $attributes['bis']);
|
||||
$travel->code = (string) $attributes['code'];
|
||||
$travel->type = (string) $attributes['reiseart'];
|
||||
$travel->priceFrom = $this->stringToFloat((string) $xml->abpreis);
|
||||
$travel->selectionGroups = $this->getSelectionGroups($xml);
|
||||
$travel->additionalServices = $this->getAdditionalServices($xml);
|
||||
$travel->transportationServices = $this->getTransportationServices($xml);
|
||||
$travel->rooms = $this->getRooms($hotelXml);
|
||||
$travel->pickups = $this->getPickups($xml);
|
||||
|
||||
return $travel;
|
||||
}
|
||||
|
||||
public function getSelectionGroups(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$selectionGroups = [];
|
||||
|
||||
foreach ($xml->selektiongruppe as $item) {
|
||||
$groupId = (int) $item->attributes()['idbuspro'];
|
||||
$selectionGroup = new CrmSelectionGroup();
|
||||
$selectionGroup->id = $groupId;
|
||||
$selectionGroup->label = (string) $item->attributes()['bezeichnung'];
|
||||
|
||||
foreach ($item->selektion as $subItem) {
|
||||
$selectionId = (int) $subItem->attributes()['idbuspro'];
|
||||
$selection = new CrmSelection();
|
||||
$selection->id = $selectionId;
|
||||
$selection->label = (string) $subItem->attributes()['bezeichnung'];
|
||||
$selectionGroups[$groupId]['selections'][$selectionId] = (string) $subItem->attributes()['bezeichnung'];
|
||||
$selectionGroup->selections[] = $selection;
|
||||
}
|
||||
|
||||
$selectionGroups[$groupId] = $selectionGroup;
|
||||
}
|
||||
|
||||
return $selectionGroups;
|
||||
}
|
||||
|
||||
public function getAdditionalServices(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$additionalServices = [];
|
||||
|
||||
foreach ($xml->lei_sonstiges->leistung as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$serviceId = (int) $attributes['idbuspro'];
|
||||
|
||||
$service = new Service();
|
||||
$service->source = Service::SOURCE_TRAVEL;
|
||||
$service->category = Service::CATEGORY_ADDITIONAL;
|
||||
$service->id = $serviceId;
|
||||
$service->subType = (string) $attributes['unterart'];
|
||||
$service->mandatory = $this->stringToBool((string) $attributes['pflicht']);
|
||||
$service->dateFrom = $this->stringToDate((string) $attributes['termin']);
|
||||
$service->dateTo = $this->stringToDate((string) $attributes['bis']);
|
||||
$service->label = (string) $item->text;
|
||||
$service->price = $this->stringToFloat((string) $item->preis);
|
||||
$service->status = (string) $item->status;
|
||||
|
||||
$additionalServices[$serviceId] = $service;
|
||||
}
|
||||
|
||||
return $additionalServices;
|
||||
}
|
||||
|
||||
public function getGuideForTransportationService(\SimpleXMLElement $xmlTransportationService): ?Guide
|
||||
{
|
||||
if (null === $xmlTransportationService->reiseleiter) {
|
||||
return null;
|
||||
}
|
||||
|
||||
$guide = new Guide();
|
||||
$guide->name = $xmlTransportationService->reiseleiter->name;
|
||||
$guide->phone = $xmlTransportationService->reiseleiter->telefon;
|
||||
|
||||
return $guide;
|
||||
}
|
||||
|
||||
public function getTransportationServices(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$transportationServices = [];
|
||||
|
||||
foreach ($xml->lei_befoerderung->leistung as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$serviceId = (int) $attributes['idbuspro'];
|
||||
|
||||
$service = new Service();
|
||||
$service->source = Service::SOURCE_TRAVEL;
|
||||
$service->category = Service::CATEGORY_TRANSPORTATION;
|
||||
$service->id = $serviceId;
|
||||
$service->subType = (string) $attributes['unterart'];
|
||||
$service->dateFrom = $this->stringToDate((string) $attributes['termin']);
|
||||
$service->dateTo = $this->stringToDate((string) $attributes['bis']);
|
||||
$service->label = (string) $item->text;
|
||||
$service->price = $this->stringToFloat((string) $item->preis);
|
||||
$service->direction = (string) $item->richtung;
|
||||
|
||||
$transportationServices[$serviceId] = $service;
|
||||
}
|
||||
|
||||
return $transportationServices;
|
||||
}
|
||||
|
||||
public function getPickups(\SimpleXMLElement $xml): array
|
||||
{
|
||||
$pickups = [];
|
||||
|
||||
foreach ($xml->zustiege->zustieg as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$pickupId = (int) $attributes['idbuspro'];
|
||||
|
||||
$pickup = new Pickup();
|
||||
$pickup->id = $pickupId;
|
||||
$pickup->time = $this->stringToDateTime((string) $attributes['zeit']);
|
||||
$pickup->price = $attributes['preis'] ? $this->stringToFloat((string) $attributes['preis']) : null;
|
||||
|
||||
$pickups[$pickupId] = $pickup;
|
||||
}
|
||||
|
||||
return $pickups;
|
||||
}
|
||||
|
||||
public function getHotelXml(\SimpleXMLElement $xml, ?int $hotelId): ?\SimpleXMLElement
|
||||
{
|
||||
// In case not hotel id is provided, take the first hotel node (which is most probably the only one)
|
||||
if (null === $hotelId) {
|
||||
return $xml->hotel;
|
||||
}
|
||||
|
||||
$hotelXml = $xml->xpath(sprintf('//hotel[@idbuspro="%d"]', $hotelId));
|
||||
|
||||
return $hotelXml[0] ?? null;
|
||||
}
|
||||
|
||||
public function getRooms(\SimpleXMLElement $xml): array
|
||||
{
|
||||
if (false === isset($xml->zimmer)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$rooms = [];
|
||||
|
||||
foreach ($xml->zimmer->preis as $item) {
|
||||
$attributes = $item->attributes();
|
||||
$roomId = (int) $attributes['idbuspro_zimmer'];
|
||||
|
||||
$room = new Room();
|
||||
$room->id = $roomId;
|
||||
$room->code = (string) $attributes['zimmercode'];
|
||||
$room->category = (string) $attributes['kat'];
|
||||
$room->boardId = (int) $attributes['idbuspro_vp'];
|
||||
$room->label = (string) $attributes['zimmertext'];
|
||||
$room->minPax = (int) $attributes['MinPax'];
|
||||
$room->maxPax = (int) $attributes['MaxPax'];
|
||||
$room->nights = (int) $attributes['naechte'];
|
||||
$room->price = $attributes['preis'] ? $this->stringToFloat((string) $attributes['preis']) : null;
|
||||
$room->status = (string) $item->status;
|
||||
$room->available = (int) $attributes['verfuegbar'];
|
||||
|
||||
$rooms[$roomId] = $room;
|
||||
}
|
||||
|
||||
return $rooms;
|
||||
}
|
||||
|
||||
public function patchMutability(Travel $travel, BaseData $mutableData): void
|
||||
{
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_ADDITIONAL_SERVICES)) {
|
||||
$travel->additionalServicesMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_TRANSPORTATION)) {
|
||||
$travel->transportationServicesMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PICKUP)) {
|
||||
$travel->pickupsMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_ACCOMMODATION)) {
|
||||
$travel->roomsMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PARTICIPANT_COUNT)) {
|
||||
$travel->participantCountMutable = $item->mutable;
|
||||
}
|
||||
|
||||
if (null !== $item = $mutableData->getItemByKey(MutableData::CATEGORY_PARTICIPANT_DATA)) {
|
||||
$travel->participantDataMutable = $item->mutable;
|
||||
}
|
||||
}
|
||||
|
||||
public function patchAvailabilities(Travel $travel, BaseData $availabilities): void
|
||||
{
|
||||
$serviceAvailabilities = $availabilities->getItems();
|
||||
|
||||
foreach ([...$travel->additionalServices, ...$travel->transportationServices] as $service) {
|
||||
if (array_key_exists($service->id, $serviceAvailabilities)) {
|
||||
$service->available = $serviceAvailabilities[$service->id]->available;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function patchBookings(BaseData $bookings): void
|
||||
{
|
||||
foreach ($bookings->getItems() as $booking) {
|
||||
if (null === $travelId = $booking->travelId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$booking->travelData = $this->loadById($travelId);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user