Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

merge time ranges takes in to account the data field. #269

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
Open
30 changes: 18 additions & 12 deletions src/OpeningHours.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,29 +144,32 @@ public static function createFromStructuredData(

/**
* @param array $data hours definition array or sub-array
* @param bool $ignoreData should ignore data
* @param array $excludedKeys keys to ignore from parsing
* @return array
*/
public static function mergeOverlappingRanges(array $data, array $excludedKeys = ['data', 'dateTimeClass', 'filters', 'overflow']): array
public static function mergeOverlappingRanges(array $data, bool $ignoreData = true, array $excludedKeys = ['data', 'dateTimeClass', 'filters', 'overflow']): array
{
$result = [];
$ranges = [];

foreach (static::filterHours($data, $excludedKeys) as $key => $value) {
foreach (static::filterHours($data, $excludedKeys) as $key => [$value, $data]) {
$dataString = $ignoreData ? '' : json_encode($data);

$value = is_array($value)
? static::mergeOverlappingRanges($value, ['data'])
: (is_string($value) ? TimeRange::fromString($value) : $value);
? static::mergeOverlappingRanges($value, $ignoreData)
: (is_string($value) ? TimeRange::fromString($value, $data) : $value);

if ($value instanceof TimeRange) {
$newRanges = [];

foreach ($ranges as $range) {
foreach (($ranges[$dataString] ?? []) as $range) {
if ($value->format() === $range->format()) {
continue 2;
}

if ($value->overlaps($range) || $range->overlaps($value)) {
$value = TimeRange::fromList([$value, $range]);
$value = TimeRange::fromList([$value, $range], $data);

continue;
}
Expand All @@ -175,7 +178,7 @@ public static function mergeOverlappingRanges(array $data, array $excludedKeys =
}

$newRanges[] = $value;
$ranges = $newRanges;
$ranges[$dataString] = $newRanges;

continue;
}
Expand All @@ -184,7 +187,9 @@ public static function mergeOverlappingRanges(array $data, array $excludedKeys =
}

foreach ($ranges as $range) {
$result[] = $range;
foreach ((array) $range as $rangeItem) {
$result[] = $rangeItem;
}
}

return $result;
Expand All @@ -205,11 +210,12 @@ public static function mergeOverlappingRanges(array $data, array $excludedKeys =
* } $data
* @param string|DateTimeZone|null $timezone
* @param string|DateTimeZone|null $outputTimezone
* @param bool $ignoreData
* @return static
*/
public static function createAndMergeOverlappingRanges(array $data, $timezone = null, $outputTimezone = null): self
public static function createAndMergeOverlappingRanges(array $data, $timezone = null, $outputTimezone = null, bool $ignoreData = true): self
{
return static::create(static::mergeOverlappingRanges($data), $timezone, $outputTimezone);
return static::create(static::mergeOverlappingRanges($data, $ignoreData), $timezone, $outputTimezone);
}

/**
Expand Down Expand Up @@ -1034,13 +1040,13 @@ private static function filterHours(array $data, array $excludedKeys): Generator

if (is_int($key) && is_array($value) && isset($value['hours'])) {
foreach ((array) $value['hours'] as $subKey => $hour) {
yield "$key.$subKey" => $hour;
yield "$key.$subKey" => [$hour, $value['data'] ?? null];
}

continue;
}

yield $key => $value;
yield $key => [$value, null];
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/OpeningHoursForDay.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static function fromStrings(array $strings, mixed $data = null): static
uasort($strings, static fn ($a, $b) => strcmp(static::getHoursFromRange($a), static::getHoursFromRange($b)));

return new static(
Arr::map($strings, static fn ($string) => TimeRange::fromDefinition($string)),
Arr::map($strings, static fn ($string) => $string instanceof TimeRange ? $string : TimeRange::fromDefinition($string)),
$data,
);
}
Expand Down
4 changes: 2 additions & 2 deletions src/TimeRange.php
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ public static function fromDefinition($value): self
return is_array($value) ? static::fromArray($value) : static::fromString($value);
}

public static function fromList(array $ranges): self
public static function fromList(array $ranges, $data = null): self
{
if (count($ranges) === 0) {
throw InvalidTimeRangeList::create();
Expand All @@ -88,7 +88,7 @@ public static function fromList(array $ranges): self
}
}

return new self($start, $end);
return new self($start, $end, $data);
}

public static function fromMidnight(Time $end, $data = null): self
Expand Down
25 changes: 25 additions & 0 deletions tests/OpeningHoursFillTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,31 @@ public function it_should_merge_ranges_including_explicit_24_00()
], $dump);
}

#[Test]
public function it_should_merge_ranges_and_keep_data()
{
$hours = OpeningHours::createAndMergeOverlappingRanges([
'monday' => [
['hours' => '08:00-12:00', 'data' => ['testdata' => true]],
['hours' => '12:00-24:00', 'data' => ['testdata' => true]],
['hours' => '05:00-08:00', 'data' => ['testdata' => false]],
],
], null, null, false);
$dump = [];
$data = null;
/** @var TimeRange $range */
foreach ($hours->forDay('monday') as $range) {
$data = $range->data;
$dump[] = $range->format();
}

$this->assertSame([
'05:00-08:00',
'08:00-24:00',
], $dump);
$this->assertSame(['testdata' => true], $data);
}

#[Test]
public function it_should_reorder_ranges()
{
Expand Down