where('set_id', $dto->set->getId()) ->where('kind', $dto->kind) ->exists(); if ($kindExists) { throw new DomainException( 'level kind must be unique within set', ); } $currentMaximum = SetLevelModel::query() ->where('set_id', $dto->set->getId()) ->max('depth'); $depth = $currentMaximum === null ? 0 : (int) $currentMaximum + 1; $model = SetLevelModel::create([ 'set_id' => $dto->set->getId(), 'kind' => $dto->kind, 'depth' => $depth, ]); return new SetLevel( id: $model->id, set: $dto->set, kind: $model->kind, depth: $model->depth, ); } public function find(int $id): ?SetLevel { $model = SetLevelModel::find($id); return $model === null ? null : $this->toDomain($model); } public function findBySet(Set $set): array { $models = SetLevelModel::query() ->where('set_id', $set->getId()) ->orderBy('depth') ->orderBy('id') ->get(); $levels = []; foreach ($models as $model) { $levels[] = new SetLevel( id: $model->id, set: $set, kind: $model->kind, depth: $model->depth, ); } return $levels; } private function toDomain(SetLevelModel $model): SetLevel { $set = $this->setRepository->find($model->set_id); if ($set === null) { throw new RuntimeException('set level set not found'); } return new SetLevel( id: $model->id, set: $set, kind: $model->kind, depth: $model->depth, ); } }