From 6b539f43f36f07da318ac9096b9f8498997d3118 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Fromme?= Date: Tue, 29 Sep 2026 12:08:07 +0200 Subject: [PATCH] fix: skip travels whose hotel is missing from the master data --- src/BusProNet/XmlLoader/TravelLoader.php | 7 ++ .../XmlLoader/TravelLoaderFilesMapTest.php | 65 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/BusProNet/XmlLoader/TravelLoaderFilesMapTest.php diff --git a/src/BusProNet/XmlLoader/TravelLoader.php b/src/BusProNet/XmlLoader/TravelLoader.php index 63c801ec..ab4945dd 100644 --- a/src/BusProNet/XmlLoader/TravelLoader.php +++ b/src/BusProNet/XmlLoader/TravelLoader.php @@ -92,6 +92,13 @@ class TravelLoader extends AbstractLoader ->each(function (Crawler $hotelNode) use (&$mapping, $hotels, $travelId) { $hotelId = (int) $hotelNode->attr('idbuspro'); + // A travel may reference a hotel that hotel.xml does not carry. + // Reading ->name off the miss would fatal the whole mapping, not + // just this entry, and take /api/travels down with it. + if (false === isset($hotels[$hotelId])) { + return; + } + $mapping[$travelId]['hotels'][$hotelId] = [ 'id' => $hotelId, 'code' => $hotelNode->attr('code'), diff --git a/tests/BusProNet/XmlLoader/TravelLoaderFilesMapTest.php b/tests/BusProNet/XmlLoader/TravelLoaderFilesMapTest.php new file mode 100644 index 00000000..39f8b242 --- /dev/null +++ b/tests/BusProNet/XmlLoader/TravelLoaderFilesMapTest.php @@ -0,0 +1,65 @@ + + + + + Skiwoche + + + + +'; + + /** + * A travel may reference a hotel id that hotel.xml does not carry. Before the guard the + * miss was dereferenced, which fataled the whole cached mapping rather than one entry -- + * so /api/travels went down entirely, not just the affected travel. + */ + public function testGenerateFilesMapSkipsHotelsMissingFromMasterData(): void + { + $known = new Hotel(); + $known->id = 1; + $known->name = 'Hotel Bekannt'; + + $hotelLoader = $this->createStub(HotelLoader::class); + $hotelLoader->method('loadAll')->willReturn([1 => $known]); + + $filesystem = $this->createStub(FilesystemOperator::class); + $filesystem->method('listContents')->willReturn( + new DirectoryListing([new FileAttributes('Ziel_1.xml')]) + ); + $filesystem->method('read')->willReturn(self::XML); + + $loader = new TravelLoader( + $hotelLoader, + $this->createStub(TravelParser::class), + 'https://example.test', + new TagAwareAdapter(new ArrayAdapter()), + $filesystem, + ); + + $mapping = $loader->generateFilesMap(); + + $this->assertArrayHasKey(900, $mapping); + $this->assertSame([1], array_keys($mapping[900]['hotels'])); + $this->assertSame('Hotel Bekannt', $mapping[900]['hotels'][1]['label']); + } +}