parentElementId === null) { throw new BadRequestException('parentElementId is required'); } if ($request->childElementIds === null) { throw new BadRequestException('childElementIds is required'); } $parentElement = $this->elementRepository->find( $request->parentElementId, ); if ($parentElement === null) { throw new NotFoundException('Parent element not found'); } $childElementIds = $this->validatedChildElementIds( $request->childElementIds, ); $directChildElementIds = $this->elementIds( $this->elementRepository->findByParentElement($parentElement), ); $this->validateNoDuplicateIds($childElementIds); $this->validateAllIdsAreDirectChildren( $childElementIds, $directChildElementIds, ); $this->validateEveryDirectChildWasSubmitted( $childElementIds, $directChildElementIds, ); return $this->elementRepository->reorderChildren( $parentElement, $childElementIds, ); } /** * @param mixed[] $childElementIds * @return int[] * @throws BadRequestException */ private function validatedChildElementIds(array $childElementIds): array { $validatedChildElementIds = []; foreach ($childElementIds as $childElementId) { if (! is_int($childElementId)) { throw new BadRequestException( 'childElementIds must contain integers', ); } $validatedChildElementIds[] = $childElementId; } return $validatedChildElementIds; } /** * @param int[] $childElementIds * @throws BadRequestException */ private function validateNoDuplicateIds(array $childElementIds): void { $seenChildElementIds = []; foreach ($childElementIds as $childElementId) { if (isset($seenChildElementIds[$childElementId])) { throw new BadRequestException( 'Child order contains duplicate ids', ); } $seenChildElementIds[$childElementId] = true; } } /** * @param int[] $childElementIds * @param int[] $directChildElementIds * @throws BadRequestException */ private function validateAllIdsAreDirectChildren( array $childElementIds, array $directChildElementIds, ): void { $directChildElementIdsById = []; foreach ($directChildElementIds as $directChildElementId) { $directChildElementIdsById[$directChildElementId] = true; } foreach ($childElementIds as $childElementId) { if (! isset($directChildElementIdsById[$childElementId])) { throw new BadRequestException( 'Child order contains invalid child', ); } } } /** * @param int[] $childElementIds * @param int[] $directChildElementIds * @throws BadRequestException */ private function validateEveryDirectChildWasSubmitted( array $childElementIds, array $directChildElementIds, ): void { if (count($childElementIds) === count($directChildElementIds)) { return; } throw new BadRequestException( 'Child order must include every direct child', ); } /** * @param Element[] $elements * @return int[] */ private function elementIds(array $elements): array { $elementIds = []; foreach ($elements as $element) { $elementIds[] = $element->getId(); } return $elementIds; } }