Skip to content

Commit

Permalink
Allow date ranges as input
Browse files Browse the repository at this point in the history
  • Loading branch information
kylekatarnls committed Nov 5, 2023
1 parent b352fa7 commit 0fad569
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 7 deletions.
11 changes: 11 additions & 0 deletions src/Exceptions/InvalidDateRange.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Spatie\OpeningHours\Exceptions;

class InvalidDateRange extends Exception
{
public static function invalidDateRange(string $entry, string $date): self
{
return new self("Unable to record `$entry` as it would override `$date`.");
}
}
77 changes: 70 additions & 7 deletions src/OpeningHours.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@

namespace Spatie\OpeningHours;

use DateInterval;
use DatePeriod;
use DateTime;
use DateTimeImmutable;
use DateTimeInterface;
use DateTimeZone;
use Generator;
use Spatie\OpeningHours\Exceptions\Exception;
use Spatie\OpeningHours\Exceptions\InvalidDate;
use Spatie\OpeningHours\Exceptions\InvalidDateRange;
use Spatie\OpeningHours\Exceptions\InvalidDateTimeClass;
use Spatie\OpeningHours\Exceptions\InvalidDayName;
use Spatie\OpeningHours\Exceptions\InvalidTimezone;
Expand Down Expand Up @@ -703,27 +706,87 @@ protected function parseOpeningHoursAndExceptions(array $data): array
{
$dateTimeClass = Arr::pull($data, 'dateTimeClass', null);
$metaData = Arr::pull($data, 'data', null);
$exceptions = [];
$filters = Arr::pull($data, 'filters', []);
$overflow = (bool) Arr::pull($data, 'overflow', false);
[$exceptions, $filters] = $this->parseExceptions(
Arr::pull($data, 'exceptions', []),
Arr::pull($data, 'filters', []),
);
$openingHours = $this->parseDaysOfWeeks($data);

return [$openingHours, $exceptions, $metaData, $filters, $overflow, $dateTimeClass];
}

foreach (Arr::pull($data, 'exceptions', []) as $key => $exception) {
protected function parseExceptions(array $data, array $filters): array
{
$exceptions = [];

foreach ($data as $key => $exception) {
if (is_callable($exception)) {
$filters[] = $exception;

continue;
}

$exceptions[$key] = $exception;
foreach ($this->readDatesRange($key) as $date) {
if (isset($exceptions[$date])) {
throw InvalidDateRange::invalidDateRange($key, $date);
}

$exceptions[$date] = $exception;
}
}

return [$exceptions, $filters];
}

protected function parseDaysOfWeeks(array $data): array
{
$openingHours = [];

foreach ($data as $day => $openingHoursData) {
$openingHours[$this->normalizeDayName($day)] = $openingHoursData;
foreach ($data as $dayKey => $openingHoursData) {
foreach ($this->readDatesRange($dayKey) as $rawDay) {
$day = $this->normalizeDayName($rawDay);

if (isset($openingHours[$day])) {
throw InvalidDateRange::invalidDateRange($dayKey, $day);
}

$openingHours[$day] = $openingHoursData;
}
}

return [$openingHours, $exceptions, $metaData, $filters, $overflow, $dateTimeClass];
return $openingHours;
}

protected function readDatesRange(string $key): iterable
{
$toChunks = preg_split('/\sto\s/', $key, 2);

if (count($toChunks) === 2) {
return $this->daysBetween(trim($toChunks[0]), trim($toChunks[1]));
}

$dashChunks = explode('-', $key);
$chunksCount = count($dashChunks);

if ($chunksCount >= 4) {
$middle = ceil($chunksCount / 2);

return $this->daysBetween(
trim(implode('-', array_slice($dashChunks, 0, $middle))),
trim(implode('-', array_slice($dashChunks, $middle))),
);
}

return [$key];
}

protected function daysBetween(string $start, string $end): DatePeriod
{
$startDate = new DateTimeImmutable($start);
$endDate = $startDate->modify($end)->modify('+12 hours');

return new DatePeriod($startDate, new DateInterval('P1D'), $endDate);
}

protected function setOpeningHoursFromStrings(string $day, array $openingHours): void
Expand Down

0 comments on commit 0fad569

Please sign in to comment.