1<?php
2
3// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the GNU Affero General Public License v3.0.
4// See the LICENCE file in the repository root for full licence text.
5
6namespace App\Http\Controllers\Solo;
7
8use App\Http\Controllers\Controller as BaseController;
9use App\Libraries\ClientCheck;
10use App\Models\ScoreToken;
11use App\Models\Solo\Score;
12use App\Transformers\ScoreTransformer;
13use DB;
14
15class ScoresController extends BaseController
16{
17 public function __construct()
18 {
19 $this->middleware('auth');
20 }
21
22 public function store($beatmapId, $tokenId)
23 {
24 $request = \Request::instance();
25 $clientTokenData = ClientCheck::parseToken($request);
26 $score = DB::transaction(function () use ($beatmapId, $request, $tokenId) {
27 $user = auth()->user();
28 $scoreToken = ScoreToken::where([
29 'beatmap_id' => $beatmapId,
30 'user_id' => $user->getKey(),
31 ])->lockForUpdate()->findOrFail($tokenId);
32
33 $beatmapsetApprovedAt = $scoreToken->beatmap?->beatmapset?->approved_date;
34 if ($beatmapsetApprovedAt !== null && $scoreToken->created_at->isBefore($beatmapsetApprovedAt)) {
35 abort(422, 'beatmapset state has been updated');
36 }
37
38 // return existing score otherwise (assuming duplicated submission)
39 if ($scoreToken->score_id === null) {
40 $params = Score::extractParams($request->all(), $scoreToken);
41 $score = Score::createFromJsonOrExplode($params);
42 $scoreToken->fill(['score_id' => $score->getKey()])->saveOrExplode();
43 } else {
44 // assume score exists and is valid
45 $score = $scoreToken->score;
46 }
47
48 return $score;
49 });
50
51 if ($score->wasRecentlyCreated) {
52 ClientCheck::queueToken($clientTokenData, $score->getKey());
53 $score->queueForProcessing();
54 }
55
56 return json_item($score, new ScoreTransformer(ScoreTransformer::TYPE_SOLO));
57 }
58}