Commit d02c0188 authored by Jacob Priddy's avatar Jacob Priddy 👌
Browse files

Actually parse schedule for events

parent 4a02ee7d
......@@ -5,8 +5,10 @@ namespace Source\UseCases\Door\StatusResponse;
use Carbon\Carbon;
use Source\Entities\Override;
use Source\Entities\Schedule;
use InvalidArgumentException;
use Source\Gateways\Overrides\OverridesRepository;
use Source\Gateways\DoorSchedule\DoorScheduleRepository;
use Source\Gateways\RecurrenceSet\RecurrenceSetRepository;
class StatusResponse implements StatusResponseUseCase
{
......@@ -20,17 +22,27 @@ class StatusResponse implements StatusResponseUseCase
*/
protected DoorScheduleRepository $schedules;
/**
* @var \Source\Gateways\RecurrenceSet\RecurrenceSetRepository
*/
protected RecurrenceSetRepository $rset;
/**
* The only things that can change the status of a door is a schedule or an override
* So we look at schedules and overrides to get the status events.
*
* @param \Source\Gateways\DoorSchedule\DoorScheduleRepository $schedules
* @param \Source\Gateways\Overrides\OverridesRepository $overrides
* @param \Source\Gateways\DoorSchedule\DoorScheduleRepository $schedules
* @param \Source\Gateways\Overrides\OverridesRepository $overrides
* @param \Source\Gateways\RecurrenceSet\RecurrenceSetRepository $rset
*/
public function __construct(DoorScheduleRepository $schedules, OverridesRepository $overrides)
{
public function __construct(
DoorScheduleRepository $schedules,
OverridesRepository $overrides,
RecurrenceSetRepository $rset
) {
$this->overrides = $overrides;
$this->schedules = $schedules;
$this->rset = $rset;
}
/**
......@@ -69,42 +81,52 @@ class StatusResponse implements StatusResponseUseCase
$response = new ResponseModel();
if ($override && $override->hasTypeOf(Override::TYPE_LOCKED)) {
foreach ($openSchedules as $schedule) {
// If the beginning of the schedule overlaps with the override
$overlapBegin = $override->isActiveForDate($schedule->getStart());
// If the end of the schedule overlaps with the override
$overlapEnd = $override->isActiveForDate($schedule->getEnd());
if (!$overlapBegin && !$overlapEnd) {
if ($schedule->isActiveForDate($override->getStart())) {
// Override is enclosed by the schedule break up the open event
$response->addEvent(new OpenEvent($schedule->getStart(), $override->getStart()));
$response->addEvent(new OpenEvent($override->getEnd(), $schedule->getEnd()));
} else {
// override does not overlap with schedule add whole schedule range
$response->addEvent(new OpenEvent($schedule->getStart(), $schedule->getEnd()));
if ($override && $override->hasTypeOf(Override::TYPE_OPEN)) {
$response->addEvent(new OpenEvent($override->getStart(), $override->getEnd()));
$override = null;
}
foreach ($openSchedules as $schedule) {
try {
$this->rset->parse($schedule->getRset());
} catch (InvalidArgumentException $e) {
continue;
}
foreach ($this->rset->occurrencesBetween($begin, $end) as $eventStart) {
if ($override) {
$eventEnd = $eventStart->clone()->addRealMilliseconds($schedule->getDuration());
// If the beginning of the schedule overlaps with the override
$overlapBegin = $override->isActiveForDate($eventStart);
// If the end of the schedule overlaps with the override
$overlapEnd = $override->isActiveForDate($eventEnd);
if (!$overlapBegin && !$overlapEnd) {
if ($eventStart->isBefore($override->getStart()) && $eventEnd->isAfter($override->getEnd())) {
// Override is enclosed by the event, break up the open event
$response->addEvent(new OpenEvent($eventStart, $override->getStart()));
$response->addEvent(new OpenEvent($override->getEnd(), $eventEnd));
} else {
// override does not overlap with event add whole event range
$response->addEvent(new OpenEvent($eventStart, $eventEnd));
}
}
}
if ($overlapBegin && $overlapEnd) {
// Override envelops the schedule, ignore it
continue;
}
if ($overlapBegin && $overlapEnd) {
// Override envelops the event, ignore it
continue;
}
if ($overlapBegin) {
$response->addEvent(new OpenEvent($override->getEnd(), $schedule->getEnd()));
if ($overlapBegin) {
$response->addEvent(new OpenEvent($override->getEnd(), $schedule->getEnd()));
} else {
$response->addEvent(new OpenEvent($schedule->getStart(), $override->getStart()));
}
} else {
$response->addEvent(new OpenEvent($schedule->getStart(), $override->getStart()));
// No override to worry about, add the open event.
$eventEnd = $eventStart->clone()->addRealMilliseconds($schedule->getDuration());
$response->addEvent(new OpenEvent($eventStart, $eventEnd));
}
}
} else {
if ($override && $override->hasTypeOf(Override::TYPE_OPEN)) {
$response->addEvent(new OpenEvent($override->getStart(), $override->getEnd()));
}
foreach ($openSchedules as $schedule) {
$response->addEvent(new OpenEvent($schedule->getStart(), $schedule->getEnd()));
}
}
$presenter->present($response);
......
......@@ -8,6 +8,7 @@ use Illuminate\Contracts\Foundation\Application;
use Source\Gateways\Overrides\OverridesRepository;
use Illuminate\Contracts\Support\DeferrableProvider;
use Source\Gateways\DoorSchedule\DoorScheduleRepository;
use Source\Gateways\RecurrenceSet\RecurrenceSetRepository;
/**
* Service provider must be registered in AppServiceProvider
......@@ -24,7 +25,8 @@ class StatusResponseUseCaseServiceProvider extends ServiceProvider implements De
$this->app->bind(StatusResponseUseCase::class, static function (Application $app) {
return new StatusResponse(
$app->make(DoorScheduleRepository::class),
$app->make(OverridesRepository::class)
$app->make(OverridesRepository::class),
$app->make(RecurrenceSetRepository::class)
);
});
}
......
<?php
namespace Tests\Unit\Source\UseCases\Door\StatusResponse;
use Source\UseCases\Door\StatusResponse\Presenter;
use Source\UseCases\Door\StatusResponse\ResponseModel;
class PresenterStub implements Presenter
{
public ResponseModel $response;
protected bool $presenterCalled = false;
/**
* @inheritDoc
*/
public function present(ResponseModel $responseModel): void
{
$this->presenterCalled = true;
$this->response = $responseModel;
}
public function wasPresenterCalled(): bool
{
return $this->presenterCalled;
}
/**
* @inheritDoc
*/
public function getViewModel(): array
{
return [];
}
}
<?php
namespace Tests\Unit\Source\UseCases\Door\StatusResponse;
use Carbon\Carbon;
use Source\Entities\Override;
use Source\Entities\Schedule;
use PHPUnit\Framework\TestCase;
use Source\UseCases\Door\StatusResponse\ResponseModel;
use Source\UseCases\Door\StatusResponse\StatusResponse;
use Source\Gateways\Overrides\InMemoryOverridesRepository;
use Source\Gateways\DoorSchedule\InMemoryDoorScheduleRepository;
class StatusResponseTest extends TestCase
{
/**
* @var \Source\Gateways\DoorSchedule\InMemoryDoorScheduleRepository
*/
protected InMemoryDoorScheduleRepository $doorSchedules;
/**
* @var \Source\Gateways\Overrides\InMemoryOverridesRepository
*/
protected InMemoryOverridesRepository $overrides;
/**
* @var \Source\UseCases\Door\StatusResponse\StatusResponse
*/
protected StatusResponse $useCase;
/**
* @var \Tests\Unit\Source\UseCases\Door\StatusResponse\PresenterStub
*/
protected PresenterStub $presenter;
/**
* @var \Source\UseCases\Door\StatusResponse\ResponseModel
*/
protected ResponseModel $response;
public function setUp(): void
{
parent::setUp();
$this->doorSchedules = new InMemoryDoorScheduleRepository();
$this->overrides = new InMemoryOverridesRepository();
$this->useCase = new StatusResponse($this->doorSchedules, $this->overrides);
$this->presenter = new PresenterStub();
}
protected function handleTest(string $doorId, Carbon $begin, Carbon $end): void
{
$this->useCase->getStatusForDoor($doorId, $begin, $end, $this->presenter);
$this->response = $this->presenter->response;
}
/**
* @test
*/
public function it_returns_empty_if_no_schedules_or_overrides(): void
{
$this->handleTest('1', Carbon::now(), Carbon::now()->addDay());
$this->assertEquals([], $this->response->getEvents());
}
/**
* @test
*/
public function it_adds_override_events(): void
{
$override = $this->overrides->addOverride(new Override(
1,
'ree',
1,
1,
Override::TYPE_OPEN,
Carbon::now()->addSecond(),
Carbon::now()->addMinute()
));
$this->handleTest('1', Carbon::now(), Carbon::now()->addSeconds(30));
$this->assertCount(1, $this->response->getEvents());
$this->assertEquals($override->getStart(), $this->response->getEvents()[0]->getBegin());
}
/**
* @test
*/
public function it_adds_schedules_without_overrides(): void
{
$this->doorSchedules->attachScheduleToDoor('1', new Schedule(
1,
1,
Schedule::TYPE_OPEN_MODE,
'',
''
));
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment