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\Jobs;
7
8use App\Exceptions\AuthorizationException;
9use App\Models\Beatmapset;
10use App\Models\Event;
11use App\Models\Log;
12use App\Models\User;
13use Carbon\Carbon;
14use Exception;
15use Illuminate\Bus\Queueable;
16use Illuminate\Contracts\Queue\ShouldQueue;
17use Illuminate\Foundation\Bus\Dispatchable;
18use Illuminate\Queue\InteractsWithQueue;
19use Illuminate\Queue\SerializesModels;
20
21class BeatmapsetDelete implements ShouldQueue
22{
23 use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
24
25 /** @var Beatmapset */
26 private $beatmapset;
27
28 /** @var User */
29 private $user;
30
31 public function __construct(Beatmapset $beatmapset, User $user)
32 {
33 $this->user = $user;
34 $this->beatmapset = $beatmapset;
35 }
36
37 public function handle()
38 {
39 // Extra check that doesn't get bypassed by admin permissions.
40 if ($this->beatmapset->isScoreable()) {
41 throw new AuthorizationException('This beatmap is no longer deleteable.');
42 }
43
44 $this->beatmapset->getConnection()->transaction(function () {
45 if ($this->beatmapset->user_id === $this->user->user_id) {
46 Event::generate(
47 'beatmapsetDelete',
48 ['beatmapset' => $this->beatmapset, 'user' => $this->user]
49 );
50 } else {
51 Log::log([
52 'log_data' => array_only($this->beatmapset->getAttributes(), ['beatmapset_id', 'title']),
53 'log_time' => Carbon::now(),
54 'log_type' => Log::LOG_BEATMAPSET_MOD,
55 'log_ip' => request()->ip(),
56 'log_operation' => 'LOG_BEATMAPSET_DELETE',
57 'user_id' => $this->user->user_id,
58 ]);
59 }
60
61 // won't update already deleted beatmaps which is what we want.
62 $this->beatmapset->beatmaps()->delete();
63 if ($this->beatmapset->delete() === false) {
64 // something internal probably went wrong, so just force a rollback.
65 throw new Exception('Failed to delete beatmapset.');
66 }
67
68 // only update the non-deleted comments.
69 $this->beatmapset->comments()->withoutTrashed()->update([
70 'deleted_by_id' => $this->user->getKey(),
71 // can restore comments >= than this date if really needed when undeleting.
72 'deleted_at' => $this->beatmapset->deleted_at,
73 ]);
74
75 if ($this->beatmapset->topic !== null) {
76 $this->beatmapset->topic->delete();
77 }
78 });
79 }
80}