validate($request); $startDate = new DateTimeImmutable($request->dateStart); $endDate = new DateTimeImmutable($request->dateEnd); $userId = $request->userId; $user = $this->userRepo->find($userId); if ($user === null) { throw new DomainException("User with id: $userId doesnt exist"); } $textId = $request->textId; $text = $this->textRepo->find($textId); if ($text === null) { throw new DomainException("Text with id: $textId doesnt exist"); } $nodesOfText = $this->filterForNonParentNodes( $this->nodeRepo->findByTextId($textId) ); $plan = $this->planRepo->create(new CreatePlanDto( name: $request->name, user: $user, )); $dates = []; $currentDate = $startDate; while ($currentDate <= $endDate) { $dates[] = $currentDate; $currentDate = $currentDate->modify('+1 day'); } $nodesPerDay = (int) ceil(count($nodesOfText) / count($dates)); foreach ($nodesOfText as $index => $node) { $dateIndex = (int) floor($index / $nodesPerDay); $scheduledDate = $dates[$dateIndex]; $this->createScheduledNode->execute( new CreateScheduledNodeRequest( date: $scheduledDate->format('Y-m-d'), planId: $plan->getId(), ) ); } return $plan; } /** * @param Node[] $nodes * @return Node[] */ private function filterForNonParentNodes(array $nodes): array { $result = []; foreach ($nodes as $node) { $result[$node->getId()] = $node; $parentNode = $node->getParentNode(); if ($parentNode !== null) { unset($result[$parentNode->getId()]); } } return array_values($result); } private function validate(CreatePlanRequest $request): void { if ($request->userId === null) { throw new BadRequestException('userId is required'); } if ($request->textId === null) { throw new BadRequestException('textId is required'); } if ($request->name === null) { throw new BadRequestException('name is required'); } if ($request->dateStart === null) { throw new BadRequestException('date start is required'); } if ($request->dateEnd === null) { throw new BadRequestException('date end is required'); } $startDate = new DateTimeImmutable($request->dateStart); $endDate = new DateTimeImmutable($request->dateEnd); if ($endDate < $startDate) { throw new BadRequestException('date end cannot be before date start'); } } }