*/ private array $excludedLabels; public function __construct( private HttpClientInterface $client, private string $holidayUrl, private CacheInterface $cache, string $excludedLabels = '', ) { $this->excludedLabels = array_values(array_filter( array_map('trim', explode(',', $excludedLabels)), static fn (string $label): bool => '' !== $label, )); } /** * @throws TransportExceptionInterface * @throws ServerExceptionInterface * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface * @throws Exception */ public function getHolidaysDay(string $zone): array { $zone = strtolower(trim($zone)); $key = "public_holidays_{$zone}_all"; $holidays = $this->cache->get($key, function (ItemInterface $item) use ($zone): array { $item->expiresAfter(30 * 86400); $url = $this->holidayUrl."{$zone}.json"; try { $response = $this->client->request( 'GET', $url ); } catch (TransportExceptionInterface) { throw new RuntimeException('Unable to reach public holidays API.'); } catch (ClientExceptionInterface) { throw new RuntimeException('Invalid zone provided for public holidays.'); } catch (ServerExceptionInterface) { throw new RuntimeException('Public holidays API is temporarily unavailable.'); } catch (Throwable) { throw new RuntimeException('Unexpected error while fetching public holidays.'); } return json_decode($response->getContent(), true); }); return $this->applyExclusions($holidays); } /** * @throws TransportExceptionInterface * @throws ServerExceptionInterface * @throws RedirectionExceptionInterface * @throws ClientExceptionInterface */ public function getHolidaysDayByYears(string $zone, string $years): array { return $this->applyExclusions($this->fetchHolidaysByYears($zone, $years)); } public function getRawHolidaysDayByYears(string $zone, string $years): array { return $this->fetchHolidaysByYears($zone, $years); } /** * @return array */ private function fetchHolidaysByYears(string $zone, string $years): array { $zone = strtolower(trim($zone)); $years = trim($years); $key = "public_holidays_{$zone}_{$years}"; return $this->cache->get($key, function (ItemInterface $item) use ($zone, $years): array { $item->expiresAfter(30 * 86400); $url = $this->holidayUrl."{$zone}/{$years}.json"; try { $response = $this->client->request('GET', $url); } catch (TransportExceptionInterface) { throw new RuntimeException('Unable to reach public holidays API.'); } catch (ClientExceptionInterface) { throw new RuntimeException('Invalid zone or year provided for public holidays.'); } catch (ServerExceptionInterface) { throw new RuntimeException('Public holidays API is temporarily unavailable.'); } catch (Throwable) { throw new RuntimeException('Unexpected error while fetching public holidays.'); } return json_decode($response->getContent(), true); }); } /** * @param array $holidays * * @return array */ private function applyExclusions(array $holidays): array { if ([] === $this->excludedLabels) { return $holidays; } return array_filter( $holidays, fn (string $label): bool => !in_array($label, $this->excludedLabels, true), ); } }