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

158 lines
4.2 KiB
PHP

<?php
namespace App\Http\Controllers;
use App\Enums\RoomStateChange;
use App\Events\RoomStateChanged;
use App\Models\Player;
use App\Models\Room;
use App\Models\Vote;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
use Illuminate\Validation\ValidationException;
class RoundController extends Controller
{
public function reset(
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);
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.',
]);
}
}
}