*/ public function loadAll(?string $filename = 'hotel.xml'): array { try { return $this->cache->get('bpn_hotels', function (ItemInterface $item) use ($filename) { $item->expiresAfter(3 * 60 * 60); $item->tag(['xml-sync']); $hotels = []; $this ->loadXml($filename) ->filterXPath('//hotels/hotel') ->each(function (Crawler $node) use (&$hotels) { $id = (int) $node->attr('idbuspro'); $hotels[$id] = $this->parseXml($node); }) ; return $hotels; }); } catch (InvalidArgumentException $e) { return []; } } public function mapCodeToId(string $hotelCode, ?string $filename = 'hotel.xml'): ?int { return $this->loadByCode($hotelCode, $filename)?->id; } public function loadByCode(string $hotelCode, ?string $filename = 'hotel.xml'): ?Hotel { $hotels = $this->loadAll($filename); foreach ($hotels as $hotel) { if ($hotelCode === $hotel->code) { return $hotel; } } return null; } /** * @throws HotelNotFoundException */ public function loadById(int $id, ?string $filename = 'hotel.xml'): Hotel { $hotels = $this->loadAll($filename); if (false === isset($hotels[$id])) { throw new HotelNotFoundException($id); } return $hotels[$id]; } private function loadXml(?string $filename = 'hotel.xml'): Crawler { $xml = $this->xmlExport->read($filename); return XmlCrawlerFactory::create($xml); } public function parseXml(Crawler $node): Hotel { $hotel = new Hotel(); $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')); // String, never int: see Hotel::$costUnit. $hotel->costUnit = $this->getStringOrNullValue($node->filterXPath('//kostenstelle')); // `country` itself stays the raw token — it is the join key into /api/countries[].token. $hotel->countryCode = $this->countryCodeMapper->map($hotel->country); return $hotel; } public function patchHotelDetails(Travel $travel): void { $hotelId = $travel->hotelId; if (null === $hotelId) { $travel->hotel = null; return; } try { $hotel = $this->loadById($hotelId); $travel->hotel = $hotel; } catch (HotelNotFoundException $e) { // If hotel details can't be loaded, leave travel->hotel as null // This allows the travel to be processed even if hotel details are missing $travel->hotel = null; } } }