Files
scrum-poker-internal/app/Http/Controllers/RoomPlayerController.php
T

83 lines
2.3 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\RoomStateChange;
use App\Events\RoomStateChanged;
use App\Http\Requests\JoinRoomRequest;
use App\Models\Player;
use App\Models\Room;
use Illuminate\Http\RedirectResponse;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
class RoomPlayerController extends Controller
{
public function join(JoinRoomRequest $request): RedirectResponse
{
$validated = $request->validated();
$user = $request->user();
[$room, $player] = DB::transaction(function () use ($request, $validated, $user): array {
$room = Room::query()
->where('join_code', $validated['join_code'])
->lockForUpdate()
->firstOrFail();
if ($room->isClosed()) {
throw ValidationException::withMessages([
'join_code' => 'Dieser Raum ist geschlossen.',
]);
}
$player = $this->existingPlayer($request, $room);
if ($player === null) {
$player = $room->players()->create([
'user_id' => $user?->id,
'name' => $validated['player_name'],
'is_moderator' => false,
'last_seen_at' => now(),
]);
} else {
$player->update(['last_seen_at' => now()]);
}
$room->update([
'last_activity_at' => now(),
'state_version' => $room->state_version + 1,
]);
return [$room, $player];
});
$request->session()->put(
"room_players.{$room->id}",
$player->id,
);
RoomStateChanged::dispatch(
$room->id,
$room->state_version,
RoomStateChange::PlayerJoined,
);
return to_route('room.show', $room);
}
private function existingPlayer(JoinRoomRequest $request, Room $room): ?Player
{
if ($request->user() !== null) {
return $room->players()
->where('user_id', $request->user()->id)
->first();
}
$playerId = $request->session()->get("room_players.{$room->id}");
return is_numeric($playerId)
? $room->players()->find((int) $playerId)
: null;
}
}