the browser-facing portion of osu!
at master 6.3 kB view raw
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; 7 8use App\Exceptions\ModelNotSavedException; 9use App\Libraries\BeatmapsetDiscussion\Review; 10use App\Libraries\BeatmapsetDiscussionsBundle; 11use App\Models\BeatmapDiscussion; 12use App\Models\Beatmapset; 13use Auth; 14 15/** 16 * @group Beatmapset Discussions 17 */ 18class BeatmapDiscussionsController extends Controller 19{ 20 public function __construct() 21 { 22 $this->middleware('auth', ['except' => ['index', 'mediaUrl', 'show']]); 23 $this->middleware('require-scopes:public', ['only' => ['index']]); 24 25 parent::__construct(); 26 } 27 28 public function allowKudosu($id) 29 { 30 $discussion = BeatmapDiscussion::findOrFail($id); 31 priv_check('BeatmapDiscussionAllowOrDenyKudosu', $discussion)->ensureCan(); 32 33 try { 34 $discussion->allowKudosu(Auth::user()); 35 } catch (ModelNotSavedException $e) { 36 return error_popup($e->getMessage()); 37 } 38 39 return $discussion->beatmapset->defaultDiscussionJson(); 40 } 41 42 public function denyKudosu($id) 43 { 44 $discussion = BeatmapDiscussion::findOrFail($id); 45 priv_check('BeatmapDiscussionAllowOrDenyKudosu', $discussion)->ensureCan(); 46 47 try { 48 $discussion->denyKudosu(Auth::user()); 49 } catch (ModelNotSavedException $e) { 50 return error_popup($e->getMessage()); 51 } 52 53 return $discussion->beatmapset->defaultDiscussionJson(); 54 } 55 56 public function destroy($id) 57 { 58 $discussion = BeatmapDiscussion::whereNull('deleted_at')->findOrFail($id); 59 priv_check('BeatmapDiscussionDestroy', $discussion)->ensureCan(); 60 61 try { 62 $discussion->softDeleteOrExplode(Auth::user()); 63 } catch (ModelNotSavedException $e) { 64 return error_popup($e->getMessage()); 65 } 66 67 return $discussion->beatmapset->defaultDiscussionJson(); 68 } 69 70 /** 71 * Get Beatmapset Discussions 72 * 73 * Returns a list of beatmapset discussions. 74 * 75 * --- 76 * 77 * ### Response Format 78 * 79 * <aside class="warning"> 80 * The response of this endpoint is likely to change soon! 81 * </aside> 82 * 83 * Field | Type | Description 84 * ------------------------- | ----------------------------------------------- | ----------- 85 * beatmaps | [BeatmapExtended](#beatmapextended)[] | List of beatmaps associated with the discussions returned. 86 * cursor_string | [CursorString](#cursorstring) | | 87 * discussions | [BeatmapsetDiscussion](#beatmapsetdiscussion)[] | List of discussions according to `sort` order. 88 * included_discussions | [BeatmapsetDiscussion](#beatmapsetdiscussion)[] | Additional discussions related to `discussions`. 89 * reviews_config.max_blocks | integer | Maximum number of blocks allowed in a review. 90 * users | [User](#user)[] | List of users associated with the discussions returned. 91 * 92 * @usesCursor 93 * @queryParam beatmap_id `id` of the [Beatmap](#beatmap). 94 * @queryParam beatmapset_id `id` of the [Beatmapset](#beatmapset). 95 * @queryParam beatmapset_status One of `all`, `ranked`, `qualified`, `disqualified`, `never_qualified`. Defaults to `all`. TODO: better descriptions. 96 * @queryParam limit Maximum number of results. 97 * @queryParam message_types[] `suggestion`, `problem`, `mapper_note`, `praise`, `hype`, `review`. Blank defaults to all types. TODO: better descriptions. 98 * @queryParam only_unresolved `true` to show only unresolved issues; `false`, otherwise. Defaults to `false`. 99 * @queryParam page Search result page. 100 * @queryParam sort `id_desc` for newest first; `id_asc` for oldest first. Defaults to `id_desc`. 101 * @queryParam user The `id` of the [User](#user). 102 * @queryParam with_deleted This param has no effect as api calls do not currently receive group permissions. 103 */ 104 public function index() 105 { 106 $bundle = new BeatmapsetDiscussionsBundle(request()->all()); 107 108 $json = $bundle->toArray(); 109 110 if (is_api_request()) { 111 return $json; 112 } 113 114 $paginator = $bundle->getPaginator(); 115 $search = $bundle->getSearchParams(); 116 117 return ext_view('beatmap_discussions.index', compact('json', 'search', 'paginator')); 118 } 119 120 public function restore($id) 121 { 122 $discussion = BeatmapDiscussion::whereNotNull('deleted_at')->findOrFail($id); 123 priv_check('BeatmapDiscussionRestore', $discussion)->ensureCan(); 124 125 $discussion->restore(Auth::user()); 126 127 return $discussion->beatmapset->defaultDiscussionJson(); 128 } 129 130 public function review($beatmapsetId) 131 { 132 $beatmapset = Beatmapset::findOrFail($beatmapsetId); 133 134 priv_check('BeatmapsetDiscussionReviewStore', $beatmapset)->ensureCan(); 135 136 try { 137 $document = json_decode(request()->all()['document'] ?? '[]', true); 138 Review::create($beatmapset, $document, Auth::user()); 139 } catch (\Exception $e) { 140 return error_popup($e->getMessage(), 422); 141 } 142 143 return $beatmapset->defaultDiscussionJson(); 144 } 145 146 public function show($id) 147 { 148 $discussion = BeatmapDiscussion::findOrFail($id); 149 150 if ($discussion->beatmapset === null) { 151 abort(404); 152 } 153 154 return ujs_redirect(route('beatmapsets.discussion', $discussion->beatmapset).'#/'.$discussion->getKey()); 155 } 156 157 public function vote($id) 158 { 159 $discussion = BeatmapDiscussion::findOrFail($id); 160 161 priv_check('BeatmapDiscussionVote', $discussion)->ensureCan(); 162 163 $params = get_params(\Request::all(), 'beatmap_discussion_vote', ['score:int']); 164 $params['user_id'] = Auth::user()->user_id; 165 166 if ($discussion->vote($params)) { 167 return $discussion->beatmapset->defaultDiscussionJson(); 168 } else { 169 return error_popup(osu_trans('beatmaps.discussion-votes.update.error')); 170 } 171 } 172}