attributes->get('currentPlayer'); abort_unless( $player instanceof Player && $player->room_id === $room->id && $player->is_moderator, 403, ); $stateVersion = DB::transaction(function () use ($room): int { $lockedRoom = Room::query() ->lockForUpdate() ->findOrFail($room->id); $this->ensureRoomIsOpen($lockedRoom); Vote::query() ->where('room_id', $lockedRoom->id) ->where('round', $lockedRoom->current_round) ->delete(); $lockedRoom->update([ 'revealed_at' => null, 'last_activity_at' => now(), 'state_version' => $lockedRoom->state_version + 1, ]); return $lockedRoom->state_version; }); RoomStateChanged::dispatch( $room->id, $stateVersion, RoomStateChange::VotesReset, ); return back(); } public function reveal( Request $request, Room $room, ): RedirectResponse { $player = $request->attributes->get('currentPlayer'); abort_unless( $player instanceof Player && $player->room_id === $room->id && $player->is_moderator, 403, ); $stateVersion = DB::transaction(function () use ($room): int { $lockedRoom = Room::query() ->lockForUpdate() ->findOrFail($room->id); $this->ensureRoomIsOpen($lockedRoom); if ($lockedRoom->revealed_at !== null) { throw ValidationException::withMessages([ 'room' => 'Die Karten sind bereits aufgedeckt.', ]); } $lockedRoom->update([ 'revealed_at' => now(), 'last_activity_at' => now(), 'state_version' => $lockedRoom->state_version + 1, ]); return $lockedRoom->state_version; }); RoomStateChanged::dispatch( $room->id, $stateVersion, RoomStateChange::CardsRevealed, ); return back(); } public function nextRound( Request $request, Room $room, ): RedirectResponse { $player = $request->attributes->get('currentPlayer'); abort_unless( $player instanceof Player && $player->room_id === $room->id && $player->is_moderator, 403, ); $stateVersion = DB::transaction(function () use ($room): int { $lockedRoom = Room::query() ->lockForUpdate() ->findOrFail($room->id); $this->ensureRoomIsOpen($lockedRoom); if ($lockedRoom->revealed_at === null) { throw ValidationException::withMessages([ 'room' => 'Die aktuelle Runde muss zuerst aufgedeckt werden.', ]); } $lockedRoom->update([ 'current_round' => $lockedRoom->current_round + 1, 'revealed_at' => null, 'last_activity_at' => now(), 'state_version' => $lockedRoom->state_version + 1, ]); return $lockedRoom->state_version; }); RoomStateChanged::dispatch( $room->id, $stateVersion, RoomStateChange::NextRound, ); return back(); } private function ensureRoomIsOpen(Room $room): void { if ($room->isClosed()) { throw ValidationException::withMessages([ 'room' => 'Dieser Raum ist geschlossen.', ]); } } }