diff --git a/app/Http/Controllers/Api/ApiV1Controller.php b/app/Http/Controllers/Api/ApiV1Controller.php index d43a867bd..84569fa5b 100644 --- a/app/Http/Controllers/Api/ApiV1Controller.php +++ b/app/Http/Controllers/Api/ApiV1Controller.php @@ -3713,171 +3713,4 @@ class ApiV1Controller extends Controller return $this->json([]); } - - /** - * GET /api/v1/followed_tags - * - * - * @return array - */ - public function getFollowedTags(Request $request) - { - abort_if(!$request->user(), 403); - - $account = AccountService::get($request->user()->profile_id); - - $this->validate($request, [ - 'cursor' => 'sometimes', - 'limit' => 'sometimes|integer|min:1|max:200' - ]); - $limit = $request->input('limit', 100); - - $res = HashtagFollow::whereProfileId($account['id']) - ->orderByDesc('id') - ->cursorPaginate($limit)->withQueryString(); - - $pagination = false; - $prevPage = $res->nextPageUrl(); - $nextPage = $res->previousPageUrl(); - if($nextPage && $prevPage) { - $pagination = '<' . $nextPage . '>; rel="next", <' . $prevPage . '>; rel="prev"'; - } else if($nextPage && !$prevPage) { - $pagination = '<' . $nextPage . '>; rel="next"'; - } else if(!$nextPage && $prevPage) { - $pagination = '<' . $prevPage . '>; rel="prev"'; - } - - if($pagination) { - return response()->json(FollowedTagResource::collection($res)->collection) - ->header('Link', $pagination); - } - return response()->json(FollowedTagResource::collection($res)->collection); - } - - /** - * POST /api/v1/tags/:id/follow - * - * - * @return object - */ - public function followHashtag(Request $request, $id) - { - abort_if(!$request->user(), 403); - - $pid = $request->user()->profile_id; - $account = AccountService::get($pid); - - $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; - $tag = Hashtag::where('name', $operator, $id) - ->orWhere('slug', $operator, $id) - ->first(); - - abort_if(!$tag, 422, 'Unknown hashtag'); - - abort_if( - HashtagFollow::whereProfileId($pid)->count() >= HashtagFollow::MAX_LIMIT, - 422, - 'You cannot follow more than ' . HashtagFollow::MAX_LIMIT . ' hashtags.' - ); - - $follows = HashtagFollow::updateOrCreate( - [ - 'profile_id' => $account['id'], - 'hashtag_id' => $tag->id - ], - [ - 'user_id' => $request->user()->id - ] - ); - - HashtagService::follow($pid, $tag->id); - HashtagFollowService::add($tag->id, $pid); - - return response()->json(FollowedTagResource::make($follows)->toArray($request)); - } - - /** - * POST /api/v1/tags/:id/unfollow - * - * - * @return object - */ - public function unfollowHashtag(Request $request, $id) - { - abort_if(!$request->user(), 403); - - $pid = $request->user()->profile_id; - $account = AccountService::get($pid); - - $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; - $tag = Hashtag::where('name', $operator, $id) - ->orWhere('slug', $operator, $id) - ->first(); - - abort_if(!$tag, 422, 'Unknown hashtag'); - - $follows = HashtagFollow::whereProfileId($pid) - ->whereHashtagId($tag->id) - ->first(); - - if(!$follows) { - return [ - 'name' => $tag->name, - 'url' => config('app.url') . '/i/web/hashtag/' . $tag->slug, - 'history' => [], - 'following' => false - ]; - } - - if($follows) { - HashtagService::unfollow($pid, $tag->id); - HashtagFollowService::unfollow($tag->id, $pid); - HashtagUnfollowPipeline::dispatch($tag->id, $pid, $tag->slug)->onQueue('feed'); - $follows->delete(); - } - - $res = FollowedTagResource::make($follows)->toArray($request); - $res['following'] = false; - return response()->json($res); - } - - /** - * GET /api/v1/tags/:id - * - * - * @return object - */ - public function getHashtag(Request $request, $id) - { - abort_if(!$request->user(), 403); - - $pid = $request->user()->profile_id; - $account = AccountService::get($pid); - $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; - $tag = Hashtag::where('name', $operator, $id) - ->orWhere('slug', $operator, $id) - ->first(); - - if(!$tag) { - return [ - 'name' => $id, - 'url' => config('app.url') . '/i/web/hashtag/' . $id, - 'history' => [], - 'following' => false - ]; - } - - $res = [ - 'name' => $tag->name, - 'url' => config('app.url') . '/i/web/hashtag/' . $tag->slug, - 'history' => [], - 'following' => HashtagService::isFollowing($pid, $tag->id) - ]; - - if($request->has(self::PF_API_ENTITY_KEY)) { - $res['count'] = HashtagService::count($tag->id); - } - - return $this->json($res); - } } diff --git a/app/Http/Controllers/Api/V1/TagsController.php b/app/Http/Controllers/Api/V1/TagsController.php new file mode 100644 index 000000000..7314ce09d --- /dev/null +++ b/app/Http/Controllers/Api/V1/TagsController.php @@ -0,0 +1,207 @@ +json($res, $code, $headers, JSON_UNESCAPED_SLASHES); + } + + /** + * GET /api/v1/tags/:id/related + * + * + * @return array + */ + public function relatedTags(Request $request, $tag) + { + abort_unless($request->user(), 403); + $tag = Hashtag::whereSlug($tag)->firstOrFail(); + return HashtagRelatedService::get($tag->id); + } + + /** + * POST /api/v1/tags/:id/follow + * + * + * @return object + */ + public function followHashtag(Request $request, $id) + { + abort_if(!$request->user(), 403); + + $pid = $request->user()->profile_id; + $account = AccountService::get($pid); + + $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; + $tag = Hashtag::where('name', $operator, $id) + ->orWhere('slug', $operator, $id) + ->first(); + + abort_if(!$tag, 422, 'Unknown hashtag'); + + abort_if( + HashtagFollow::whereProfileId($pid)->count() >= HashtagFollow::MAX_LIMIT, + 422, + 'You cannot follow more than ' . HashtagFollow::MAX_LIMIT . ' hashtags.' + ); + + $follows = HashtagFollow::updateOrCreate( + [ + 'profile_id' => $account['id'], + 'hashtag_id' => $tag->id + ], + [ + 'user_id' => $request->user()->id + ] + ); + + HashtagService::follow($pid, $tag->id); + HashtagFollowService::add($tag->id, $pid); + + return response()->json(FollowedTagResource::make($follows)->toArray($request)); + } + + /** + * POST /api/v1/tags/:id/unfollow + * + * + * @return object + */ + public function unfollowHashtag(Request $request, $id) + { + abort_if(!$request->user(), 403); + + $pid = $request->user()->profile_id; + $account = AccountService::get($pid); + + $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; + $tag = Hashtag::where('name', $operator, $id) + ->orWhere('slug', $operator, $id) + ->first(); + + abort_if(!$tag, 422, 'Unknown hashtag'); + + $follows = HashtagFollow::whereProfileId($pid) + ->whereHashtagId($tag->id) + ->first(); + + if(!$follows) { + return [ + 'name' => $tag->name, + 'url' => config('app.url') . '/i/web/hashtag/' . $tag->slug, + 'history' => [], + 'following' => false + ]; + } + + if($follows) { + HashtagService::unfollow($pid, $tag->id); + HashtagFollowService::unfollow($tag->id, $pid); + HashtagUnfollowPipeline::dispatch($tag->id, $pid, $tag->slug)->onQueue('feed'); + $follows->delete(); + } + + $res = FollowedTagResource::make($follows)->toArray($request); + $res['following'] = false; + return response()->json($res); + } + + /** + * GET /api/v1/tags/:id + * + * + * @return object + */ + public function getHashtag(Request $request, $id) + { + abort_if(!$request->user(), 403); + + $pid = $request->user()->profile_id; + $account = AccountService::get($pid); + $operator = config('database.default') == 'pgsql' ? 'ilike' : 'like'; + $tag = Hashtag::where('name', $operator, $id) + ->orWhere('slug', $operator, $id) + ->first(); + + if(!$tag) { + return [ + 'name' => $id, + 'url' => config('app.url') . '/i/web/hashtag/' . $id, + 'history' => [], + 'following' => false + ]; + } + + $res = [ + 'name' => $tag->name, + 'url' => config('app.url') . '/i/web/hashtag/' . $tag->slug, + 'history' => [], + 'following' => HashtagService::isFollowing($pid, $tag->id) + ]; + + if($request->has(self::PF_API_ENTITY_KEY)) { + $res['count'] = HashtagService::count($tag->id); + } + + return $this->json($res); + } + + /** + * GET /api/v1/followed_tags + * + * + * @return array + */ + public function getFollowedTags(Request $request) + { + abort_if(!$request->user(), 403); + + $account = AccountService::get($request->user()->profile_id); + + $this->validate($request, [ + 'cursor' => 'sometimes', + 'limit' => 'sometimes|integer|min:1|max:200' + ]); + $limit = $request->input('limit', 100); + + $res = HashtagFollow::whereProfileId($account['id']) + ->orderByDesc('id') + ->cursorPaginate($limit) + ->withQueryString(); + + $pagination = false; + $prevPage = $res->nextPageUrl(); + $nextPage = $res->previousPageUrl(); + if($nextPage && $prevPage) { + $pagination = '<' . $nextPage . '>; rel="next", <' . $prevPage . '>; rel="prev"'; + } else if($nextPage && !$prevPage) { + $pagination = '<' . $nextPage . '>; rel="next"'; + } else if(!$nextPage && $prevPage) { + $pagination = '<' . $prevPage . '>; rel="prev"'; + } + + if($pagination) { + return response()->json(FollowedTagResource::collection($res)->collection) + ->header('Link', $pagination); + } + return response()->json(FollowedTagResource::collection($res)->collection); + } +} diff --git a/routes/api.php b/routes/api.php index 23abfc323..27e566ab3 100644 --- a/routes/api.php +++ b/routes/api.php @@ -2,6 +2,7 @@ use Illuminate\Http\Request; use App\Http\Middleware\DeprecatedEndpoint; +use App\Http\Controllers\Api\V1\TagsController; $middleware = ['auth:api','validemail']; @@ -92,10 +93,11 @@ Route::group(['prefix' => 'api'], function() use($middleware) { Route::get('markers', 'Api\ApiV1Controller@getMarkers')->middleware($middleware); Route::post('markers', 'Api\ApiV1Controller@setMarkers')->middleware($middleware); - Route::get('followed_tags', 'Api\ApiV1Controller@getFollowedTags')->middleware($middleware); - Route::post('tags/{id}/follow', 'Api\ApiV1Controller@followHashtag')->middleware($middleware); - Route::post('tags/{id}/unfollow', 'Api\ApiV1Controller@unfollowHashtag')->middleware($middleware); - Route::get('tags/{id}', 'Api\ApiV1Controller@getHashtag')->middleware($middleware); + Route::get('followed_tags', [TagsController::class, 'getFollowedTags'])->middleware($middleware); + Route::post('tags/{id}/follow', [TagsController::class, 'followHashtag'])->middleware($middleware); + Route::post('tags/{id}/unfollow', [TagsController::class, 'unfollowHashtag'])->middleware($middleware); + Route::get('tags/{id}/related', [TagsController::class, 'relatedTags'])->middleware($middleware); + Route::get('tags/{id}', [TagsController::class, 'getHashtag'])->middleware($middleware); Route::get('statuses/{id}/history', 'StatusEditController@history')->middleware($middleware); Route::put('statuses/{id}', 'StatusEditController@store')->middleware($middleware);