'required|string|max:255', 'description' => 'nullable|string', 'type' => 'required|in:single,multiple,text', 'difficulty' => 'required|integer', 'category_id' => 'nullable|exists:categories,id', 'variants' => ['array', 'nullable'], 'variants.*.id' => ['required', 'integer'], 'variants.*.text' => ['required', 'string'], 'correct_answers' => 'required|array', 'is_pending_question' => 'integer' ]; } /** * @OA\Get( * path="/api/questions", * summary="Get a paginated list of questions (paginated)", * description="Retrieve questions. Optional filter by category_id.", * tags={"Questions"}, * @OA\Parameter( * name="category_id", * in="query", * description="Filter questions by category ID", * required=false, * @OA\Schema(type="integer") * ), * @OA\Parameter( * name="page", * in="query", * description="Page number for pagination", * required=false, * @OA\Schema(type="integer", default=1) * ), * @OA\Response( * response=200, * description="Paginated list of questions", * @OA\JsonContent( * @OA\Property( * property="data", * type="array", * @OA\Items(ref="#/components/schemas/QuestionResource") * ), * @OA\Property( * property="links", * type="object", * example={ * "first": "http://localhost/api/questions?page=1", * "last": "http://localhost/api/questions?page=10", * "prev": null, * "next": "http://localhost/api/questions?page=2" * } * ), * @OA\Property( * property="meta", * type="object", * example={ * "current_page": 1, * "from": 1, * "last_page": 10, * "path": "http://localhost/api/questions", * "per_page": 15, * "to": 15, * "total": 150 * } * ) * ) * ), * @OA\Response( * response=401, * description="Unauthorized" * ) * ) */ public function index(Request $request) { $query = Question::with(['author', 'category']); if ($request->has('category_id')) { $query->where('category_id', $request->query('category_id')); } $questions = $query->paginate(self::PAGINATION_COUNT); return QuestionResource::collection($questions); } /** * @OA\Get( * path="/api/questions/{id}", * summary="Get a single question", * description="Retrieve a single question by its ID, including author and category", * tags={"Questions"}, * @OA\Parameter( * name="id", * in="path", * description="ID of the question to retrieve", * required=true, * @OA\Schema(type="integer") * ), * @OA\Response( * response=200, * description="Question retrieved successfully", * @OA\JsonContent(ref="#/components/schemas/QuestionResource") * ), * @OA\Response( * response=401, * description="Unauthorized" * ), * @OA\Response( * response=404, * description="Question not found" * ) * ) */ public function show(Question $question) { $question->load(['author', 'category']); return new QuestionResource($question); } /** * @OA\Post( * path="/api/questions", * summary="Create a new question", * description="Store a new question in the system (only admin or creator).", * tags={"Questions"}, * security={{"bearerAuth":{}}}, * @OA\RequestBody( * required=true, * @OA\JsonContent( * required={"title","type","difficulty","variants","correct_answers"}, * @OA\Property(property="title", type="string", maxLength=255, example="Sample question"), * @OA\Property(property="description", type="string", nullable=true, example="Optional description"), * @OA\Property(property="type", type="string", enum={"single","multiply","text"}, example="single"), * @OA\Property(property="difficulty", type="integer", example=2), * @OA\Property( * property="variants", * type="array", * @OA\Items( * type="object", * @OA\Property(property="id", type="integer", example=1), * @OA\Property(property="text", type="string", example="Option 1") * ) * ), * @OA\Property( * property="correct_answers", * type="array", * @OA\Items( * type="integer", * example=1 * ) * ), * @OA\Property(property="category_id", type="integer", nullable=true, example=3), * @OA\Property(property="is_pending_question", type="integer", example=0) * ) * ), * @OA\Response( * response=200, * description="Question created successfully", * @OA\JsonContent(ref="#/components/schemas/QuestionResource") * ), * @OA\Response( * response=401, * description="Unauthorized" * ), * @OA\Response( * response=422, * description="Validation error" * ) * ) */ public function store(Request $request) { $this->authorize('create', Question::class); $fields = $request->validate(self::get_field_rules()); $fields['author_id'] = $request->user()->id; $question = Question::create($fields); Log::writeLog("Question '" . $question->title . "' is created by " . $request->user()->username); return new QuestionResource($question); } /** * @OA\Put( * path="/api/questions/{id}", * summary="Update a question", * description="Update an existing question by ID (only admin or creator).", * tags={"Questions"}, * security={{"bearerAuth":{}}}, * @OA\Parameter( * name="id", * in="path", * required=true, * description="ID of the question to update", * @OA\Schema(type="integer") * ), * @OA\RequestBody( * required=true, * @OA\JsonContent( * required={"title","type","difficulty","variants","correct_answers"}, * @OA\Property(property="title", type="string", maxLength=255, example="Updated question"), * @OA\Property(property="description", type="string", nullable=true, example="Updated description"), * @OA\Property(property="type", type="string", enum={"single","multiply","text"}, example="multiply"), * @OA\Property(property="difficulty", type="integer", example=3), * @OA\Property( * property="variants", * type="array", * @OA\Items( * type="object", * @OA\Property(property="id", type="integer", example=1), * @OA\Property(property="text", type="string", example="Option 1") * ) * ), * @OA\Property( * property="correct_answers", * type="array", * @OA\Items( * type="integer", * example=1 * ) * ), * @OA\Property(property="category_id", type="integer", nullable=true, example=2), * @OA\Property(property="is_pending_question", type="integer", example=0) * ) * ), * @OA\Response( * response=200, * description="Question updated successfully", * @OA\JsonContent(ref="#/components/schemas/QuestionResource") * ), * @OA\Response( * response=401, * description="Unauthorized" * ), * @OA\Response( * response=422, * description="Validation error" * ) * ) */ public function update(Request $request, Question $question) { $this->authorize('update', $question); $fields = $request->validate(self::get_field_rules()); $fields['variants'] = json_encode($fields['variants']); $question->update($fields); Log::writeLog("Question '" . $question->title . "' is updated by " . $request->user()->username); return new QuestionResource($question); } /** * @OA\Delete( * path="/api/questions/{id}", * summary="Delete a question", * description="Delete a question by ID (only admin or creator).", * tags={"Questions"}, * security={{"bearerAuth":{}}}, * @OA\Parameter( * name="id", * in="path", * required=true, * description="ID of the question to delete", * @OA\Schema(type="integer") * ), * @OA\Response( * response=200, * description="Question deleted successfully", * @OA\JsonContent( * @OA\Property(property="message", type="string", example="The hitcount was deleted") * ) * ), * @OA\Response( * response=401, * description="Unauthorized" * ), * @OA\Response( * response=403, * description="Forbidden" * ), * @OA\Response( * response=404, * description="Question not found" * ) * ) */ public function destroy(Request $request, Question $question) { $this->authorize('delete', $question); $question->delete(); Log::writeLog("Question '" . $question->id . "' is deleted by " . $request->user()->username); return ['message' => 'The hitcount was deleted']; } }