|
| 1 | +<?php |
| 2 | + |
| 3 | +declare(strict_types=1); |
| 4 | + |
| 5 | +namespace App\Http\Controllers\Api\V1; |
| 6 | + |
| 7 | +use App\Data\TagData; |
| 8 | +use App\Exceptions\TagLimitExceededException; |
| 9 | +use App\Http\Controllers\Controller; |
| 10 | +use App\Lib\SyncStarTags; |
| 11 | +use Illuminate\Http\JsonResponse; |
| 12 | +use Illuminate\Http\Request; |
| 13 | + |
| 14 | +class ExtensionController extends Controller |
| 15 | +{ |
| 16 | + /** |
| 17 | + * The authenticated user's full tag list, used for the extension's autocomplete. |
| 18 | + */ |
| 19 | + public function tags(Request $request): JsonResponse |
| 20 | + { |
| 21 | + return response()->json([ |
| 22 | + 'tags' => TagData::collect($request->user()->tags()->withStarCount()->get()), |
| 23 | + ]); |
| 24 | + } |
| 25 | + |
| 26 | + /** |
| 27 | + * The Astral tags currently applied to a repo, keyed by its GitHub database id. |
| 28 | + * Returns an empty set (not 404) when the repo has never been tagged. |
| 29 | + */ |
| 30 | + public function repoTags(Request $request, int $databaseId): JsonResponse |
| 31 | + { |
| 32 | + $star = $request->user()->stars()->with('tags')->where('repo_id', $databaseId)->first(); |
| 33 | + |
| 34 | + return response()->json([ |
| 35 | + 'databaseId' => $databaseId, |
| 36 | + 'starExists' => (bool) $star, |
| 37 | + 'tags' => $star ? TagData::collect($star->tags) : [], |
| 38 | + ]); |
| 39 | + } |
| 40 | + |
| 41 | + /** |
| 42 | + * Replace the full set of tags on a repo, creating the star and any missing |
| 43 | + * tags. Mirrors the dashboard sync via the shared SyncStarTags action. |
| 44 | + */ |
| 45 | + public function syncTags(Request $request, SyncStarTags $syncStarTags): JsonResponse |
| 46 | + { |
| 47 | + $request->validate([ |
| 48 | + 'databaseId' => ['required', 'integer'], |
| 49 | + 'nameWithOwner' => ['required', 'string'], |
| 50 | + 'url' => ['required', 'string', 'url'], |
| 51 | + 'description' => ['nullable', 'string'], |
| 52 | + 'tags' => 'array', |
| 53 | + 'tags.*.name' => ['required_with:tags', 'string'], |
| 54 | + ]); |
| 55 | + |
| 56 | + try { |
| 57 | + $star = $syncStarTags->handle( |
| 58 | + $request->user(), |
| 59 | + (int) $request->input('databaseId'), |
| 60 | + $request->only(['nameWithOwner', 'url', 'description']), |
| 61 | + $request->input('tags', []), |
| 62 | + ); |
| 63 | + } catch (TagLimitExceededException $e) { |
| 64 | + return response()->json([ |
| 65 | + 'message' => 'Tag limit reached. An active sponsorship is required to add more tags.', |
| 66 | + 'sponsorshipRequired' => $e->ability->value, |
| 67 | + ], 403); |
| 68 | + } |
| 69 | + |
| 70 | + return response()->json([ |
| 71 | + 'databaseId' => $star->repo_id, |
| 72 | + 'tags' => TagData::collect($star->load('tags')->tags), |
| 73 | + ]); |
| 74 | + } |
| 75 | +} |
0 commit comments