From 41252d8bb9e0364ca5f692e00082f975b0c2a299 Mon Sep 17 00:00:00 2001 From: Marc Date: Tue, 10 Feb 2026 15:26:26 +0100 Subject: [PATCH] Implement URLHandlerInfoProviderInterface in BuerklinProvider (#1235) * Implement URLHandlerInfoProviderInterface in BuerklinProvider Added URL handling capabilities to BuerklinProvider. * Refactor ID extraction logic in BuerklinProvider * Add tests for BuerklinProvider URLHandlerInfoProviderInterface * Revert "Refactor ID extraction logic in BuerklinProvider" This reverts commit 5f651766362ff165b1c3082ce918189e0aa2bdd3. * Exclude 'p' from valid ID return in BuerklinProvider --- .../Providers/BuerklinProvider.php | 33 +++++++- .../Providers/BuerklinProviderTest.php | 76 +++++++++++++++++++ 2 files changed, 108 insertions(+), 1 deletion(-) diff --git a/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php b/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php index 07125c73..aa165bfe 100644 --- a/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php +++ b/src/Services/InfoProviderSystem/Providers/BuerklinProvider.php @@ -34,7 +34,7 @@ use App\Settings\InfoProviderSystem\BuerklinSettings; use Psr\Cache\CacheItemPoolInterface; use Symfony\Contracts\HttpClient\HttpClientInterface; -class BuerklinProvider implements BatchInfoProviderInterface +class BuerklinProvider implements BatchInfoProviderInterface, URLHandlerInfoProviderInterface { private const ENDPOINT_URL = 'https://www.buerklin.com/buerklinws/v2/buerklin'; @@ -636,4 +636,35 @@ class BuerklinProvider implements BatchInfoProviderInterface ); } + public function getHandledDomains(): array + { + return ['buerklin.com']; + } + + public function getIDFromURL(string $url): ?string + { + //Inputs: + //https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/ + //https://www.buerklin.com/de/p/40F1332/ + //https://www.buerklin.com/en/p/bkl-electronic/dc-connectors/072341-l/40F1332/ + //https://www.buerklin.com/en/p/40F1332/ + //The ID is the last part after the manufacturer/category/mpn segment and before the final slash + //https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/#download should also work + + $path = parse_url($url, PHP_URL_PATH); + + if (!$path) { + return null; + } + + // Ensure it's actually a product URL + if (strpos($path, '/p/') === false) { + return null; + } + + $id = basename(rtrim($path, '/')); + + return $id !== '' && $id !== 'p' ? $id : null; + } + } diff --git a/tests/Services/InfoProviderSystem/Providers/BuerklinProviderTest.php b/tests/Services/InfoProviderSystem/Providers/BuerklinProviderTest.php index 3193db89..8283b7d3 100644 --- a/tests/Services/InfoProviderSystem/Providers/BuerklinProviderTest.php +++ b/tests/Services/InfoProviderSystem/Providers/BuerklinProviderTest.php @@ -268,4 +268,80 @@ class BuerklinProviderTest extends TestCase $this->assertSame('PartX', $dto->name); $this->assertSame('https://img', $dto->preview_image_url); } + public function testGetHandledDomains(): void + { + $this->assertSame(['buerklin.com'], $this->provider->getHandledDomains()); + } + + /** + * @dataProvider buerklinIdFromUrlProvider + */ + public function testGetIDFromURLExtractsId(string $url, ?string $expected): void + { + $this->assertSame($expected, $this->provider->getIDFromURL($url)); + } + + public static function buerklinIdFromUrlProvider(): array + { + return [ + 'de long path' => [ + 'https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/', + '40F1332', + ], + 'de short path' => [ + 'https://www.buerklin.com/de/p/40F1332/', + '40F1332', + ], + 'en long path' => [ + 'https://www.buerklin.com/en/p/bkl-electronic/dc-connectors/072341-l/40F1332/', + '40F1332', + ], + 'en short path' => [ + 'https://www.buerklin.com/en/p/40F1332/', + '40F1332', + ], + 'fragment should be ignored' => [ + 'https://www.buerklin.com/de/p/bkl-electronic/niedervoltsteckverbinder/072341-l/40F1332/#download', + '40F1332', + ], + 'no trailing slash' => [ + 'https://www.buerklin.com/en/p/40F1332', + '40F1332', + ], + 'query should be ignored' => [ + 'https://www.buerklin.com/en/p/40F1332/?foo=bar', + '40F1332', + ], + 'query and fragment should be ignored' => [ + 'https://www.buerklin.com/en/p/40F1332/?foo=bar#download', + '40F1332', + ], + + // Negative cases + 'not a product url (no /p/ segment)' => [ + 'https://www.buerklin.com/de/impressum/', + null, + ], + 'path contains "p" but not "/p/"' => [ + 'https://www.buerklin.com/de/help/price/', + null, + ], + 'ends with /p/ (no id)' => [ + 'https://www.buerklin.com/de/p/', + null, + ], + 'ends with /p (no trailing slash)' => [ + 'https://www.buerklin.com/de/p', + null, + ], + 'empty string' => [ + '', + null, + ], + 'not a url string' => [ + 'not a url', + null, + ], + ]; + } }