*/ 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(), ); } }