309 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			309 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
<?php
 | 
						|
 | 
						|
declare(strict_types=1);
 | 
						|
 | 
						|
namespace App\Http\Controllers;
 | 
						|
 | 
						|
use App\Http\Requests\Post\DestroyPostRequest;
 | 
						|
use App\Http\Requests\Post\ListPostRequest;
 | 
						|
use App\Http\Requests\Post\ShowPostRequest;
 | 
						|
use App\Http\Requests\Post\StorePostRequest;
 | 
						|
use App\Http\Requests\Post\UpdatePostRequest;
 | 
						|
use App\Http\Resources\PaginableResource;
 | 
						|
use App\Http\Resources\PostCollection;
 | 
						|
use App\Http\Resources\PostResource;
 | 
						|
use App\Services\Post\PostServiceInterface;
 | 
						|
use Illuminate\Http\JsonResponse;
 | 
						|
use OpenApi\Annotations as OA;
 | 
						|
 | 
						|
final class PostController extends Controller
 | 
						|
{
 | 
						|
    public function __construct(
 | 
						|
        private readonly PostServiceInterface $postService,
 | 
						|
    )
 | 
						|
    {
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @OA\Get(
 | 
						|
     *     path="/api/v1/posts/{page}",
 | 
						|
     *     summary="List all posts",
 | 
						|
     *     description="Fetch a paginated list of all posts.",
 | 
						|
     *     tags={"Posts"},
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *         name="direction",
 | 
						|
     *         in="query",
 | 
						|
     *         description="Order posts by ascending or descending",
 | 
						|
     *         required=false,
 | 
						|
     *         @OA\Schema(
 | 
						|
     *             type="string",
 | 
						|
     *             enum={"asc", "desc"},
 | 
						|
     *             example="asc"
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *          name="order",
 | 
						|
     *          in="query",
 | 
						|
     *          description="Order posts by column name",
 | 
						|
     *          required=false,
 | 
						|
     *          @OA\Schema(
 | 
						|
     *              type="string",
 | 
						|
     *              example="title"
 | 
						|
     *          )
 | 
						|
     *      ),
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *         name="title",
 | 
						|
     *         in="query",
 | 
						|
     *         description="Filter posts by title",
 | 
						|
     *         required=false,
 | 
						|
     *         @OA\Schema(
 | 
						|
     *             type="string",
 | 
						|
     *             example="Sample Post"
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *         name="page",
 | 
						|
     *         in="path",
 | 
						|
     *         description="Pagination page number",
 | 
						|
     *         required=false,
 | 
						|
     *         @OA\Schema(
 | 
						|
     *             type="integer",
 | 
						|
     *             example=1
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=200,
 | 
						|
     *         description="Successful response",
 | 
						|
     *         @OA\JsonContent(
 | 
						|
     *             type="object",
 | 
						|
     *             @OA\Property(
 | 
						|
     *                 property="items",
 | 
						|
     *                 ref="#/components/schemas/PostCollection"
 | 
						|
     *             ),
 | 
						|
     *             @OA\Property(
 | 
						|
     *                 property="meta",
 | 
						|
     *                 type="object",
 | 
						|
     *                 description="Pagination metadata",
 | 
						|
     *                 ref="#/components/schemas/PaginableResourceMeta"
 | 
						|
     *              )
 | 
						|
     *          )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=422,
 | 
						|
     *         description="Validation error",
 | 
						|
     *         @OA\JsonContent(ref="#/components/schemas/ValidationError")
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=429,
 | 
						|
     *         description="Rate limiting. Try again later.",
 | 
						|
     *     )
 | 
						|
     * )
 | 
						|
     */
 | 
						|
    public function list(ListPostRequest $request, int $page): JsonResponse
 | 
						|
    {
 | 
						|
        $posts = $this->postService->fetchPosts(
 | 
						|
            $page,
 | 
						|
            $request->filters(),
 | 
						|
            $request->order()
 | 
						|
        );
 | 
						|
        return response()->json(PaginableResource::make($posts, PostCollection::class));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @OA\Post(
 | 
						|
     *     path="/api/v1/posts",
 | 
						|
     *     operationId="storePost",
 | 
						|
     *     tags={"Posts"},
 | 
						|
     *     summary="Create a new post",
 | 
						|
     *     description="Creates a new post in the system based on the provided input data.",
 | 
						|
     *     @OA\RequestBody(
 | 
						|
     *         description="Payload for creating a new post",
 | 
						|
     *         required=true,
 | 
						|
     *         @OA\JsonContent(
 | 
						|
     *             type="object",
 | 
						|
     *             @OA\Property(property="title", type="string", maxLength=255, example="My First Post"),
 | 
						|
     *             @OA\Property(property="content", type="string", example="This is the content of my first post."),
 | 
						|
     *             @OA\Property(property="category_id", type="integer", example=1),
 | 
						|
     *             @OA\Property(property="tags", type="array", @OA\Items(type="string", example="Laravel")),
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=201,
 | 
						|
     *         description="Post successfully created",
 | 
						|
     *         @OA\JsonContent(
 | 
						|
     *             type="object",
 | 
						|
     *             @OA\Property(property="status", type="string", example="success"),
 | 
						|
     *             @OA\Property(property="message", type="string", example="Post created successfully."),
 | 
						|
     *             @OA\Property(
 | 
						|
     *                 property="data",
 | 
						|
     *                 type="object",
 | 
						|
     *                 ref="#/components/schemas/PostResource"
 | 
						|
     *             )
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=422,
 | 
						|
     *         description="Validation error",
 | 
						|
     *         @OA\JsonContent(ref="#/components/schemas/ValidationError")
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=429,
 | 
						|
     *         description="Rate limiting. Try again later.",
 | 
						|
     *     )
 | 
						|
     * )
 | 
						|
     */
 | 
						|
    public function store(StorePostRequest $request): JsonResponse
 | 
						|
    {
 | 
						|
        return response()->json(PostResource::make($this->postService->storePost($request->all())), 201);
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @OA\Get(
 | 
						|
     *     path="/api/v1/posts/{id}",
 | 
						|
     *     operationId="getPostById",
 | 
						|
     *     tags={"Posts"},
 | 
						|
     *     summary="Get a specific post by ID",
 | 
						|
     *     description="Returns a specific post identified by its unique ID.",
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *         name="id",
 | 
						|
     *         in="path",
 | 
						|
     *         description="ID of the post to retrieve",
 | 
						|
     *         required=true,
 | 
						|
     *         @OA\Schema(type="integer", example=1)
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=200,
 | 
						|
     *         description="Post data retrieved successfully",
 | 
						|
     *         @OA\JsonContent(
 | 
						|
     *             type="object",
 | 
						|
     *             @OA\Property(property="status", type="string", example="success"),
 | 
						|
     *             @OA\Property(
 | 
						|
     *                 property="data",
 | 
						|
     *                 type="object",
 | 
						|
     *                 ref="#/components/schemas/PostResource"
 | 
						|
     *             )
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=404,
 | 
						|
     *         description="Post not found",
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=429,
 | 
						|
     *         description="Rate limiting. Try again later.",
 | 
						|
     *     )
 | 
						|
     * )
 | 
						|
     */
 | 
						|
    public function show(ShowPostRequest $request, int $id): JsonResponse
 | 
						|
    {
 | 
						|
        $post = $this->postService->findPost($id);
 | 
						|
 | 
						|
        if ($post === null) {
 | 
						|
            return response()->json(null, 404);
 | 
						|
        }
 | 
						|
 | 
						|
        return response()->json(PostResource::make($post));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @OA\Put(
 | 
						|
     *     path="/api/v1/post/{id}",
 | 
						|
     *     operationId="updatePost",
 | 
						|
     *     tags={"Posts"},
 | 
						|
     *     summary="Update a specific post by ID",
 | 
						|
     *     description="Updates specific fields of a post identified by its unique ID.",
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *         name="id",
 | 
						|
     *         in="path",
 | 
						|
     *         description="ID of the post to update",
 | 
						|
     *         required=true,
 | 
						|
     *         @OA\Schema(type="integer", example=1)
 | 
						|
     *     ),
 | 
						|
     *     @OA\RequestBody(
 | 
						|
     *         description="Payload for updating a post",
 | 
						|
     *         required=true,
 | 
						|
     *         @OA\JsonContent(
 | 
						|
     *             type="object",
 | 
						|
     *             @OA\Property(property="title", type="string", maxLength=255, example="Updated Title"),
 | 
						|
     *             @OA\Property(property="content", type="string", example="Updated content of the post."),
 | 
						|
     *             @OA\Property(property="category_id", type="integer", example=2),
 | 
						|
     *             @OA\Property(property="tags", type="array", @OA\Items(type="string", example="Laravel"))
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=200,
 | 
						|
     *         description="Post data updated sucessfully",
 | 
						|
     *         @OA\JsonContent(
 | 
						|
     *             type="object",
 | 
						|
     *             @OA\Property(property="status", type="string", example="success"),
 | 
						|
     *             @OA\Property(
 | 
						|
     *                 property="data",
 | 
						|
     *                 type="object",
 | 
						|
     *                 ref="#/components/schemas/PostResource"
 | 
						|
     *             )
 | 
						|
     *         )
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=404,
 | 
						|
     *         description="Post not found",
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=422,
 | 
						|
     *         description="Validation error",
 | 
						|
     *         @OA\JsonContent(ref="#/components/schemas/ValidationError")
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=429,
 | 
						|
     *         description="Rate limiting. Try again later.",
 | 
						|
     *     )
 | 
						|
     * )
 | 
						|
     */
 | 
						|
    public function update(UpdatePostRequest $request, int $id): JsonResponse
 | 
						|
    {
 | 
						|
        $post = $this->postService->updatePost($request->all(), $id);
 | 
						|
 | 
						|
        if ($post === null) {
 | 
						|
            return response()->json(null, 404);
 | 
						|
        }
 | 
						|
 | 
						|
        return response()->json(PostResource::make($post));
 | 
						|
    }
 | 
						|
 | 
						|
    /**
 | 
						|
     * @OA\Delete(
 | 
						|
     *     path="/api/v1/post/{id}",
 | 
						|
     *     operationId="deletePost",
 | 
						|
     *     tags={"Posts"},
 | 
						|
     *     summary="Delete a specific post by ID",
 | 
						|
     *     description="Deletes a specific post identified by its unique ID. This operation is irreversible.",
 | 
						|
     *     @OA\Parameter(
 | 
						|
     *         name="id",
 | 
						|
     *         in="path",
 | 
						|
     *         description="ID of the post to delete",
 | 
						|
     *         required=true,
 | 
						|
     *         @OA\Schema(type="integer", example=1)
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=204,
 | 
						|
     *         description="Post successfully deleted",
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=404,
 | 
						|
     *         description="Post not found",
 | 
						|
     *     ),
 | 
						|
     *     @OA\Response(
 | 
						|
     *         response=429,
 | 
						|
     *         description="Rate limiting. Try again later.",
 | 
						|
     *     )
 | 
						|
     * )
 | 
						|
     */
 | 
						|
    public function destroy(DestroyPostRequest $post, int $id): JsonResponse
 | 
						|
    {
 | 
						|
        $isSuccessfullyDeleted = $this->postService->deletePost($id);
 | 
						|
        return match ($isSuccessfullyDeleted) {
 | 
						|
            false => response()->json(null, 404),
 | 
						|
            true => response()->json(null, 204),
 | 
						|
        };
 | 
						|
    }
 | 
						|
}
 |