Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 13 additions & 13 deletions src/Agenda/SingleDateRangeAgenda.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,39 @@
namespace Puntodev\Bookables\Agenda;


use Carbon\Carbon;
use Carbon\CarbonInterface;
use Exception;
use League\Period\Period;
use Puntodev\Bookables\Contracts\Agenda;

class SingleDateRangeAgenda implements Agenda
{
private Carbon $start;
private CarbonInterface $start;

private Carbon $end;
private CarbonInterface $end;

/**
* SingleDateRangeAgenda constructor.
*
* @param Carbon $start
* @param Carbon $end
* @param CarbonInterface $start
* @param CarbonInterface $end
*/
public function __construct(Carbon $start, Carbon $end)
public function __construct(CarbonInterface $start, CarbonInterface $end)
{
$this->start = $start->clone();
$this->end = $end->clone();
$this->start = $start->toImmutable();
$this->end = $end->toImmutable();
}

/**
* @param Carbon $from
* @param Carbon $to
* @param CarbonInterface $from
* @param CarbonInterface $to
* @return array|Period[]
* @throws Exception
*/
public function possibleRanges(Carbon $from, Carbon $to): array
public function possibleRanges(CarbonInterface $from, CarbonInterface $to): array
{
$maxStart = $from->max($this->start);
$minEnd = $to->min($this->end);
$maxStart = $from->toImmutable()->max($this->start);
$minEnd = $to->toImmutable()->min($this->end);
if ($maxStart->isAfter($minEnd)) {
return [];
}
Expand Down
27 changes: 14 additions & 13 deletions src/Agenda/WeeklyScheduleAgenda.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@

namespace Puntodev\Bookables\Agenda;

use Carbon\Carbon;
use DateInterval;
use DatePeriod;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriodImmutable;
use Exception;
use League\Period\Period;
use Puntodev\Bookables\Contracts\Agenda;
Expand All @@ -20,28 +21,28 @@ public function __construct(WeeklySchedule $weeklySchedule)
}

/**
* @param Carbon $from
* @param Carbon $to
* @param CarbonInterface $from
* @param CarbonInterface $to
* @return array
* @throws Exception
*/
public function possibleRanges(Carbon $from, Carbon $to): array
public function possibleRanges(CarbonInterface $from, CarbonInterface $to): array
{
$startOfDateFrom = $from->clone()->startOfDay();
$endOfDateTo = $to->clone()->endOfDay();
$startOfDateFrom = $from->toImmutable()->startOfDay();
$endOfDateTo = $to->toImmutable()->endOfDay();

$period = new DatePeriod(
$period = new CarbonPeriodImmutable(
$startOfDateFrom,
new DateInterval('P1D'),
new CarbonInterval('P1D'),
$endOfDateTo,
);

$ret = [];
foreach ($period as $date) {
$carbon = Carbon::instance($date);
$carbon = CarbonImmutable::instance($date);
foreach ($this->weeklySchedule->forDate($carbon) as $range) {
$periodStart = $startOfDateFrom->max($carbon->clone()->setTimeFromTimeString($range['start']));
$periodEnd = $endOfDateTo->min($carbon->clone()->setTimeFromTimeString($range['end']));
$periodStart = $startOfDateFrom->max($carbon->setTimeFromTimeString($range['start']));
$periodEnd = $endOfDateTo->min($carbon->setTimeFromTimeString($range['end']));
if ($periodEnd->isAfter($periodStart)) {
$ret[] = Period::fromDate($periodStart, $periodEnd);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Contracts/Agenda.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
namespace Puntodev\Bookables\Contracts;


use Carbon\Carbon;
use Carbon\CarbonInterface;

interface Agenda
{
public function possibleRanges(Carbon $from, Carbon $to): array;
public function possibleRanges(CarbonInterface $from, CarbonInterface $to): array;
}
7 changes: 4 additions & 3 deletions src/Contracts/TimeBookable.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@
namespace Puntodev\Bookables\Contracts;


use Carbon\Carbon;

use Carbon\CarbonInterface;

interface TimeBookable
{
public function available(Carbon $start, Carbon $end): array;
public function available(CarbonInterface $start, CarbonInterface $end): array;

public function unavailable(Carbon $start, Carbon $end): array;
public function unavailable(CarbonInterface $start, CarbonInterface $end): array;
}
9 changes: 5 additions & 4 deletions src/Contracts/TimeSlotter.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,16 @@

namespace Puntodev\Bookables\Contracts;

use Carbon\Carbon;

use Carbon\CarbonInterface;

interface TimeSlotter
{
/**
* Creates time slots for dates in the range between $startDate and $endDate
* @param Carbon $startDate
* @param Carbon $endDate
* @param CarbonInterface $startDate
* @param CarbonInterface $endDate
* @return array
*/
public function makeSlotsForDates(Carbon $startDate, Carbon $endDate): array;
public function makeSlotsForDates(CarbonInterface $startDate, CarbonInterface $endDate): array;
}
21 changes: 11 additions & 10 deletions src/Slots/AgendaSlotter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,27 @@
namespace Puntodev\Bookables\Slots;


use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Carbon\CarbonPeriodImmutable;
use League\Period\Period;
use Puntodev\Bookables\Contracts\Agenda;
use Puntodev\Bookables\Contracts\TimeSlotter;

/**
* TimeSlotter that uses an $agenda to obtain the date ranges for the required dates
* TimeSlotter that uses an $agenda to get the date ranges for the required dates
* and creates slots for those ranges using a particular $duration.
* If $timeBefore is specified it ensures that before each appointment there's at least $timeBefore minutes.
* If $timeAfter is specified it ensures that after each appointment there's at least $timeAfter minutes.
* If $timeBefore is specified, it ensures that before each appointment there's at least $timeBefore minutes.
* If $timeAfter is specified, it ensures that after each appointment there's at least $timeAfter minutes.
*/
class AgendaSlotter implements TimeSlotter
readonly class AgendaSlotter implements TimeSlotter
{
public function __construct(private Agenda $agenda, private int $duration, private int $timeAfter = 0, private int $timeBefore = 0)
{
}

public function makeSlotsForDates(Carbon $startDate, Carbon $endDate): array
public function makeSlotsForDates(CarbonInterface $startDate, CarbonInterface $endDate): array
{
$ranges = $this->agenda->possibleRanges($startDate, $endDate);

Expand All @@ -33,10 +34,10 @@ public function makeSlotsForDates(Carbon $startDate, Carbon $endDate): array

/** @var Period $range */
foreach ($ranges as $range) {
$dateRange = new CarbonPeriod(
Carbon::instance($range->startDate),
$dateRange = new CarbonPeriodImmutable(
CarbonImmutable::instance($range->startDate),
new CarbonInterval("PT{$interval}M"),
Carbon::instance($range->endDate)->subMinutes($this->duration),
CarbonImmutable::instance($range->endDate)->subMinutes($this->duration),
);

foreach ($dateRange as $slot) {
Expand Down
20 changes: 10 additions & 10 deletions src/Slots/DaySlotter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,40 @@
namespace Puntodev\Bookables\Slots;


use Carbon\Carbon;
use Carbon\CarbonInterface;
use Carbon\CarbonInterval;
use Carbon\CarbonPeriod;
use Carbon\CarbonPeriodImmutable;
use League\Period\Period;
use Puntodev\Bookables\Contracts\TimeSlotter;

/**
* TimeSlotter that creates slots for the whole day for each date within the requested range
* and creates slots for those dates using a particular $duration and $step.
*/
class DaySlotter implements TimeSlotter
readonly class DaySlotter implements TimeSlotter
{
public function __construct(private int $duration, private int $step)
{
}

public function makeSlotsForDates(Carbon $startDate, Carbon $endDate): array
public function makeSlotsForDates(CarbonInterface $startDate, CarbonInterface $endDate): array
{
$startOfDateFrom = $startDate->clone()->startOfDay();
$endOfDateTo = $endDate->clone()->endOfDay();
$startOfDateFrom = $startDate->toImmutable()->startOfDay();
$endOfDateTo = $endDate->toImmutable()->endOfDay();

$period = new CarbonPeriod(
$period = new CarbonPeriodImmutable(
$startOfDateFrom,
new CarbonInterval('P1D'),
$endOfDateTo,
);

$ret = [];
/** @var Carbon $date */
/** @var CarbonInterface $date */
foreach ($period as $date) {
$dateRange = new CarbonPeriod(
$dateRange = new CarbonPeriodImmutable(
$date,
new CarbonInterval("PT{$this->step}M"),
$date->clone()->addDay()->subMinutes($this->duration),
$date->addDay()->subMinutes($this->duration),
);

foreach ($dateRange as $slot) {
Expand Down
4 changes: 2 additions & 2 deletions src/WeeklySchedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Puntodev\Bookables;

use Carbon\Carbon;
use Carbon\CarbonInterface;
use DateTime;
use Exception;

Expand Down Expand Up @@ -115,7 +115,7 @@ private static function validate(array $array): void
}
}

public function forDate(Carbon $date): array
public function forDate(CarbonInterface $date): array
{
return $this->forDay(self::$dowMap[$date->dayOfWeek]);
}
Expand Down
10 changes: 5 additions & 5 deletions tests/Agenda/WeeklyScheduleAgendaTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tests\Agenda;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
use Puntodev\Bookables\Agenda\WeeklyScheduleAgenda;
Expand All @@ -19,8 +19,8 @@ public function possibleRanges(): void
$agenda = new WeeklyScheduleAgenda(WeeklySchedule::fromArray(WeeklySchedule::defaultWorkingHours()));

$result = $agenda->possibleRanges(
Carbon::parse("2020-01-19"),
Carbon::parse("2020-01-31"),
CarbonImmutable::parse("2020-01-19"),
CarbonImmutable::parse("2020-01-31"),
);

$this->assertRanges([
Expand Down Expand Up @@ -55,8 +55,8 @@ public function possibleRangesWithTimeZone(): void

$tz = "Pacific/Auckland";
$result = $agenda->possibleRanges(
Carbon::parse("2020-01-19", $tz),
Carbon::parse("2020-01-31", $tz),
CarbonImmutable::parse("2020-01-19", $tz),
CarbonImmutable::parse("2020-01-31", $tz),
);

$this->assertRanges([
Expand Down
6 changes: 3 additions & 3 deletions tests/Slots/AgendaSlotterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tests\Slots;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -32,8 +32,8 @@ public function checkForDurationAndStepping($duration, $timeAfter, $timeBefore,
$slotter = new AgendaSlotter($this->agenda, $duration, $timeAfter, $timeBefore);

$result = $slotter->makeSlotsForDates(
Carbon::parse('2020-01-23'),
Carbon::parse('2020-01-25'),
CarbonImmutable::parse('2020-01-23'),
CarbonImmutable::parse('2020-01-25'),
);

$this->assertRanges($expected, $result);
Expand Down
6 changes: 3 additions & 3 deletions tests/Slots/DaySlotterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tests\Slots;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
Expand All @@ -20,8 +20,8 @@ public function checkForDurationAndStepping($duration, $stepping, $expected): vo
$slotter = new DaySlotter($duration, $stepping);

$result = $slotter->makeSlotsForDates(
Carbon::parse('2020-01-23'),
Carbon::parse('2020-01-23'),
CarbonImmutable::parse('2020-01-23'),
CarbonImmutable::parse('2020-01-23'),
);

$this->assertRanges($expected, $result);
Expand Down
6 changes: 3 additions & 3 deletions tests/WeeklyScheduleUnitTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

namespace Tests;

use Carbon\Carbon;
use Carbon\CarbonImmutable;
use Exception;
use PHPUnit\Framework\Attributes\Test;
use PHPUnit\Framework\TestCase;
Expand Down Expand Up @@ -219,7 +219,7 @@ public function forDate(): void
$weeklySchedule = WeeklySchedule::fromJson('{"daily": {"Sun":[{"start": "14:00", "end": "15:00"}]}, "hours_in_advance": 24}');

$this->assertArrayHasKey('Sun', $weeklySchedule->daily());
$forSunday = $weeklySchedule->forDate(Carbon::parse('2020-06-14'));
$forSunday = $weeklySchedule->forDate(CarbonImmutable::parse('2020-06-14'));
$this->assertArrayHasKey('start', $forSunday[0]);
$this->assertArrayHasKey('end', $forSunday[0]);
$this->assertEquals('14:00', $forSunday[0]['start']);
Expand Down Expand Up @@ -263,7 +263,7 @@ public function forDateDisableAll(): void
$weeklySchedule = WeeklySchedule::fromJson('{"daily": {"Sun":[{"start": "14:00", "end": "15:00"}]}, "hours_in_advance": 24, "disable_all": true}');

$this->assertArrayHasKey('Sun', $weeklySchedule->daily());
$forSunday = $weeklySchedule->forDate(Carbon::parse('2020-06-14'));
$forSunday = $weeklySchedule->forDate(CarbonImmutable::parse('2020-06-14'));
$this->assertCount(0, $forSunday);
$this->assertEquals(24, $weeklySchedule->hoursInAdvance());
$this->assertTrue($weeklySchedule->disableAll());
Expand Down