267 lines
8.5 KiB
PHP
267 lines
8.5 KiB
PHP
<?php
|
|
|
|
namespace Tests\Fakes;
|
|
|
|
use App\Schedule\AssignmentForDate;
|
|
use App\Schedule\CreateScheduleDto;
|
|
use App\Schedule\RescheduleScheduleDto;
|
|
use App\Schedule\Schedule;
|
|
use App\Schedule\ScheduleAssignment;
|
|
use App\Schedule\ScheduleRepository;
|
|
use App\User\User;
|
|
use DateTimeImmutable;
|
|
use DomainException;
|
|
|
|
class FakeScheduleRepository implements ScheduleRepository
|
|
{
|
|
/**
|
|
* @var array<int, Schedule>
|
|
*/
|
|
private array $schedules = [];
|
|
|
|
private int $nextAssignmentId = 1;
|
|
|
|
public function create(CreateScheduleDto $dto): Schedule
|
|
{
|
|
$id = count($this->schedules) + 1;
|
|
$assignments = [];
|
|
|
|
foreach ($dto->assignments as $assignmentDto) {
|
|
$assignments[] = new ScheduleAssignment(
|
|
id: $this->nextAssignmentId++,
|
|
name: $assignmentDto->name,
|
|
kind: $assignmentDto->kind,
|
|
path: $assignmentDto->path,
|
|
scheduledDate: $assignmentDto->scheduledDate,
|
|
position: $assignmentDto->position,
|
|
completedAt: null,
|
|
);
|
|
}
|
|
|
|
$schedule = new Schedule(
|
|
id: $id,
|
|
user: $dto->user,
|
|
setName: $dto->setName,
|
|
elementKind: $dto->elementKind,
|
|
startDate: $dto->startDate,
|
|
targetDate: $dto->targetDate,
|
|
assignments: $assignments,
|
|
);
|
|
$this->schedules[$id] = $schedule;
|
|
|
|
return $this->copy($schedule);
|
|
}
|
|
|
|
public function reschedule(RescheduleScheduleDto $dto): Schedule
|
|
{
|
|
$schedule = $this->schedules[$dto->scheduleId] ?? null;
|
|
if ($schedule === null || $schedule->getUser()->getId()
|
|
!== $dto->user->getId()
|
|
) {
|
|
throw new DomainException(
|
|
"Schedule with id {$dto->scheduleId} not found",
|
|
);
|
|
}
|
|
|
|
$datesByAssignmentId = [];
|
|
foreach ($dto->assignments as $assignmentDto) {
|
|
$datesByAssignmentId[$assignmentDto->id] =
|
|
$assignmentDto->scheduledDate;
|
|
}
|
|
$assignments = [];
|
|
foreach ($schedule->getAssignments() as $assignment) {
|
|
$assignments[] = new ScheduleAssignment(
|
|
id: $assignment->getId(),
|
|
name: $assignment->getName(),
|
|
kind: $assignment->getKind(),
|
|
path: $assignment->getPath(),
|
|
scheduledDate: $datesByAssignmentId[$assignment->getId()]
|
|
?? $assignment->getScheduledDate(),
|
|
position: $assignment->getPosition(),
|
|
completedAt: $assignment->getCompletedAt(),
|
|
);
|
|
}
|
|
|
|
$rescheduled = new Schedule(
|
|
id: $schedule->getId(),
|
|
user: $schedule->getUser(),
|
|
setName: $schedule->getSetName(),
|
|
elementKind: $schedule->getElementKind(),
|
|
startDate: $dto->startDate,
|
|
targetDate: $dto->targetDate,
|
|
assignments: $assignments,
|
|
);
|
|
$this->schedules[$dto->scheduleId] = $rescheduled;
|
|
|
|
return $this->copy($rescheduled);
|
|
}
|
|
|
|
public function findForUser(int $id, User $user): ?Schedule
|
|
{
|
|
$schedule = $this->schedules[$id] ?? null;
|
|
if ($schedule === null || $schedule->getUser()->getId()
|
|
!== $user->getId()
|
|
) {
|
|
return null;
|
|
}
|
|
|
|
return $this->copy($schedule);
|
|
}
|
|
|
|
public function findAllForUser(User $user): array
|
|
{
|
|
$schedules = array_filter(
|
|
$this->schedules,
|
|
function (Schedule $schedule) use ($user): bool {
|
|
return $schedule->getUser()->getId() === $user->getId();
|
|
},
|
|
);
|
|
krsort($schedules);
|
|
|
|
return array_map(function (Schedule $schedule): Schedule {
|
|
return $this->copy($schedule);
|
|
}, array_values($schedules));
|
|
}
|
|
|
|
public function findIncompleteAssignmentsForUserDueOnOrBefore(
|
|
User $user,
|
|
DateTimeImmutable $date,
|
|
): array {
|
|
$assignments = [];
|
|
|
|
foreach ($this->findAllForUser($user) as $schedule) {
|
|
foreach ($schedule->getAssignments() as $assignment) {
|
|
if ($assignment->getScheduledDate() > $date
|
|
|| $assignment->getCompletedAt() !== null
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$assignments[] = new AssignmentForDate(
|
|
scheduleId: $schedule->getId(),
|
|
setName: $schedule->getSetName(),
|
|
assignment: $assignment,
|
|
);
|
|
}
|
|
}
|
|
|
|
usort(
|
|
$assignments,
|
|
function (
|
|
AssignmentForDate $first,
|
|
AssignmentForDate $second,
|
|
): int {
|
|
$firstAssignment = $first->getAssignment();
|
|
$secondAssignment = $second->getAssignment();
|
|
$dateComparison = $firstAssignment->getScheduledDate()
|
|
<=> $secondAssignment->getScheduledDate();
|
|
if ($dateComparison !== 0) {
|
|
return $dateComparison;
|
|
}
|
|
|
|
$scheduleComparison = $second->getScheduleId()
|
|
<=> $first->getScheduleId();
|
|
if ($scheduleComparison !== 0) {
|
|
return $scheduleComparison;
|
|
}
|
|
|
|
$positionComparison = $firstAssignment->getPosition()
|
|
<=> $secondAssignment->getPosition();
|
|
if ($positionComparison !== 0) {
|
|
return $positionComparison;
|
|
}
|
|
|
|
return $firstAssignment->getId()
|
|
<=> $secondAssignment->getId();
|
|
},
|
|
);
|
|
|
|
return $assignments;
|
|
}
|
|
|
|
public function findAssignmentForUser(
|
|
int $id,
|
|
User $user,
|
|
): ?ScheduleAssignment {
|
|
foreach ($this->findAllForUser($user) as $schedule) {
|
|
foreach ($schedule->getAssignments() as $assignment) {
|
|
if ($assignment->getId() === $id) {
|
|
return $this->copyAssignment($assignment);
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public function updateAssignment(
|
|
ScheduleAssignment $assignment,
|
|
): ScheduleAssignment {
|
|
foreach ($this->schedules as $id => $schedule) {
|
|
$assignments = [];
|
|
$found = false;
|
|
|
|
foreach ($schedule->getAssignments() as $storedAssignment) {
|
|
if ($storedAssignment->getId() === $assignment->getId()) {
|
|
$assignments[] = $this->copyAssignment($assignment);
|
|
$found = true;
|
|
} else {
|
|
$assignments[] = $this->copyAssignment(
|
|
$storedAssignment,
|
|
);
|
|
}
|
|
}
|
|
|
|
if ($found) {
|
|
$this->schedules[$id] = new Schedule(
|
|
id: $schedule->getId(),
|
|
user: $schedule->getUser(),
|
|
setName: $schedule->getSetName(),
|
|
elementKind: $schedule->getElementKind(),
|
|
startDate: $schedule->getStartDate(),
|
|
targetDate: $schedule->getTargetDate(),
|
|
assignments: $assignments,
|
|
);
|
|
|
|
return $this->copyAssignment($assignment);
|
|
}
|
|
}
|
|
|
|
throw new DomainException(
|
|
"Assignment with id {$assignment->getId()} not found",
|
|
);
|
|
}
|
|
|
|
private function copy(Schedule $schedule): Schedule
|
|
{
|
|
$assignments = array_map(function (
|
|
ScheduleAssignment $assignment,
|
|
): ScheduleAssignment {
|
|
return $this->copyAssignment($assignment);
|
|
}, $schedule->getAssignments());
|
|
|
|
return new Schedule(
|
|
id: $schedule->getId(),
|
|
user: $schedule->getUser(),
|
|
setName: $schedule->getSetName(),
|
|
elementKind: $schedule->getElementKind(),
|
|
startDate: $schedule->getStartDate(),
|
|
targetDate: $schedule->getTargetDate(),
|
|
assignments: $assignments,
|
|
);
|
|
}
|
|
|
|
private function copyAssignment(
|
|
ScheduleAssignment $assignment,
|
|
): ScheduleAssignment {
|
|
return new ScheduleAssignment(
|
|
id: $assignment->getId(),
|
|
name: $assignment->getName(),
|
|
kind: $assignment->getKind(),
|
|
path: $assignment->getPath(),
|
|
scheduledDate: $assignment->getScheduledDate(),
|
|
position: $assignment->getPosition(),
|
|
completedAt: $assignment->getCompletedAt(),
|
|
);
|
|
}
|
|
}
|