Files

91 lines
2.5 KiB
PHP

<?php
namespace App\Services\Rooms;
use App\Enums\RoomStateChange;
use App\Events\RoomStateChanged;
use App\Models\Player;
use App\Models\Room;
use App\Models\User;
use Illuminate\Support\Facades\DB;
class RoomLifecycleService
{
public function __construct(
private readonly RoomRealtimeStateService $realtimeState,
) {}
/**
* @return array{player: Player, was_reopened: bool}
*/
public function reopen(Room $room, User $user): array
{
[$player, $stateVersion, $wasReopened] = DB::transaction(function () use ($room, $user): array {
$lockedRoom = Room::query()
->lockForUpdate()
->findOrFail($room->id);
abort_unless($user->id === $lockedRoom->owner_id, 403);
$wasReopened = $lockedRoom->isClosed();
if ($wasReopened) {
$lockedRoom->update([
'current_round' => $lockedRoom->current_round + 1,
'revealed_at' => null,
'closed_at' => null,
'last_activity_at' => now(),
'state_version' => $lockedRoom->state_version + 1,
]);
}
return [
$lockedRoom->players()
->where('user_id', $user->id)
->firstOrFail(),
$lockedRoom->state_version,
$wasReopened,
];
});
if ($wasReopened) {
RoomStateChanged::dispatch(
$room->id,
$stateVersion,
RoomStateChange::RoomReopened,
$this->realtimeState->for($room),
);
}
return [
'player' => $player,
'was_reopened' => $wasReopened,
];
}
public function delete(Room $room, User $user): void
{
$stateVersion = DB::transaction(function () use ($room, $user): int {
$lockedRoom = Room::withTrashed()
->lockForUpdate()
->findOrFail($room->id);
abort_if($lockedRoom->trashed(), 404);
abort_unless($user->id === $lockedRoom->owner_id, 403);
$lockedRoom->update([
'state_version' => $lockedRoom->state_version + 1,
]);
$lockedRoom->delete();
return $lockedRoom->state_version;
});
RoomStateChanged::dispatch(
$room->id,
$stateVersion,
RoomStateChange::RoomDeleted,
);
}
}