diff --git a/src/Console/Commands/OpenApiCommand.php b/src/Console/Commands/OpenApiCommand.php index c5183ac8..4821b730 100644 --- a/src/Console/Commands/OpenApiCommand.php +++ b/src/Console/Commands/OpenApiCommand.php @@ -126,7 +126,7 @@ public function exec(): void return; } - if (request()->routeGroupExists('openapi', $module) && $this->fs->exists($modulePath . DS . 'resources' . DS . 'openApi' . DS . 'spec.json')) { + if (request()->routeGroupExists('openapi', $module) && $this->fs->exists($modulePath . DS . 'resources' . DS . 'openapi' . DS . 'spec.json')) { $this->error('The Open API specifications already installed for `' . ucfirst($module) . '` module'); return; } @@ -198,7 +198,7 @@ private function openapiRoutes(string $module): string $route->get("spec", function (): Quantum\Http\Response { $fs = Quantum\Storage\Factories\FileSystemFactory::get(); - return response()->json($fs->getJson(modules_dir() . "' . DS . $module . DS . 'resources' . DS . 'openapi' . DS . 'spec.json")); + return response()->json($fs->getJson(modules_dir() . DS . "' . $module . '" . DS . "resources" . DS . "openapi" . DS . "spec.json")); }); });' . PHP_EOL; } diff --git a/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAccountController.php.tpl b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAccountController.php.tpl new file mode 100644 index 00000000..2a9ddc20 --- /dev/null +++ b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAccountController.php.tpl @@ -0,0 +1,97 @@ + + * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) + * @link http://quantum.softberg.org/ + * @since 3.0.0 + */ + +namespace {{MODULE_NAMESPACE}}\Controllers\OpenApi; + +use Quantum\Http\Request; + +/** + * Class OpenApiAccountController + * @package Modules\Api + */ +abstract class OpenApiAccountController extends OpenApiController +{ + /** + * Update user info action + * @OA\Put( + * path="/api/account-settings/update", + * tags={"Account"}, + * summary="Update user info", + * operationId="updateAccount", + * security={{"bearer_token": {}}}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * required={"firstname", "lastname"}, + * @OA\Property(property="firstname", type="string"), + * @OA\Property(property="lastname", type="string"), + * example={"firstname": "Jon", "lastname": "Smit"} + * ) + * ) + * ), + * @OA\Response( + * response=200, + * description="Success", + * @OA\JsonContent( + * example={"status": "success", "message": "Updated successfully"} + * ) + * ), + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") + * ) + */ + abstract public function update(Request $request); + + /** + * Update password action + * @OA\Put( + * path="/api/account-settings/update-password", + * tags={"Account"}, + * summary="Update password", + * operationId="updatePassword", + * security={{"bearer_token": {}}}, + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * required={"current_password", "new_password", "confirm_password"}, + * @OA\Property(property="current_password", type="string"), + * @OA\Property(property="new_password", type="string"), + * @OA\Property(property="confirm_password", type="string"), + * example={"current_password": "oldPassword", "new_password": "newPassword", "confirm_password": "newPassword"} + * ) + * ) + * ), + * @OA\Response( + * response=200, + * description="Success", + * @OA\JsonContent( + * example={"status": "success", "message": "Updated successfully"} + * ) + * ), + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") + * ) + */ + abstract public function updatePassword(Request $request); +} + + diff --git a/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAuthController.php.tpl b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAuthController.php.tpl index e7295440..880c1c61 100644 --- a/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAuthController.php.tpl +++ b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiAuthController.php.tpl @@ -14,7 +14,6 @@ namespace {{MODULE_NAMESPACE}}\Controllers\OpenApi; -use Quantum\Http\Response; use Quantum\Http\Request; /** @@ -23,7 +22,6 @@ use Quantum\Http\Request; */ abstract class OpenApiAuthController extends OpenApiController { - /** * Sign in action * @OA\Post( @@ -32,36 +30,38 @@ abstract class OpenApiAuthController extends OpenApiController * summary="Sign in action", * operationId="userSignIn", * @OA\RequestBody( + * required=true, * @OA\MediaType( - * mediaType="application/json", + * mediaType="application/json", * @OA\Schema( - * @OA\Property( - * property="email", - * type="string" - * ), - * @OA\Property( - * property="password", - * type="string" - * ), - * example={"email": "rgaylord@gmail.com", "password": "password"} + * required={"email", "password"}, + * @OA\Property(property="email", type="string"), + * @OA\Property(property="password", type="string"), + * example={"email": "mail@example.com", "password": "password"} * ) * ) * ), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * oneOf={ + * @OA\Schema( + * example={ + * "status": "success", + * "tokens": { + * "access_token": "base64-jwt-token", + * "refresh_token": "refresh-token" + * } + * } + * ), + * @OA\Schema(example={"status": "success", "code": "otp_token"}) + * } * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function signin(Request $request); @@ -69,28 +69,21 @@ abstract class OpenApiAuthController extends OpenApiController /** * Gets the logged-in user data * @OA\Get( - * path="/api/me", - * tags={"User"}, - * summary="Gets the logged-in user data", - * operationId="me", - * security={ - * {"bearer_token": {}} - * }, + * path="/api/me", + * tags={"User"}, + * summary="Gets the logged-in user data", + * operationId="me", + * security={{"bearer_token": {}}}, * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "data": {"firstname": "Jon", "lastname": "Smit", "email": "mail@example.com"}} * ) * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function me(); @@ -102,34 +95,25 @@ abstract class OpenApiAuthController extends OpenApiController * tags={"Authentication"}, * summary="Sign out action", * operationId="signout", - * @OA\Parameter( - * name="refresh_token", - * description="Refresh token", - * required=true, - * in="header", - * @OA\Schema( - * type="string" - * ) - * ), + * @OA\Parameter(name="refresh_token", description="Refresh token", required=true, in="header", @OA\Schema(type="string")), + * security={{"bearer_token": {}}}, * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "tokens": { + * "access_token": "base64-jwt-token", + * "refresh_token": "refresh-token" + * } + * } * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function signout(); @@ -137,49 +121,34 @@ abstract class OpenApiAuthController extends OpenApiController /** * Sign up action * @OA\Post( - * path="/api/signup", + * path="/api/signup", * tags={"Authentication"}, * summary="Sign up action", * operationId="signUpApi", * @OA\RequestBody( + * required=true, * @OA\MediaType( * mediaType="application/json", * @OA\Schema( - * @OA\Property( - * property="email", - * type="string", - * ), - * @OA\Property( - * property="password", - * type="string" - * ), - * @OA\Property( - * property="firstname", - * type="string", - * ), - * @OA\Property( - * property="lastname", - * type="string", - * ), - * example={"email": "mail@example.com", "password": "password", "firstname": "Jon", "lastname": "Smit"} + * required={"email", "password", "firstname", "lastname"}, + * @OA\Property(property="email", type="string"), + * @OA\Property(property="password", type="string"), + * @OA\Property(property="firstname", type="string"), + * @OA\Property(property="lastname", type="string"), + * example={"email": "mail@example.com", "password": "password", "firstname": "Jon", "lastname": "Smit"} * ) * ) * ), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "message": "Successfully signed up"} * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function signup(Request $request); @@ -187,34 +156,21 @@ abstract class OpenApiAuthController extends OpenApiController /** * Activate action * @OA\Get( - * path="/api/activate/{activate_token}", + * path="/api/activate/{token}", * tags={"Authentication"}, * summary="Activate action", * operationId="activateProfile", - * @OA\Parameter( - * name="activate_token", - * description="Activate token", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * @OA\Parameter(name="token", description="Activate token", required=true, in="path", @OA\Schema(type="string")), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "message": "Account activated"} * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function activate(Request $request); @@ -222,18 +178,17 @@ abstract class OpenApiAuthController extends OpenApiController /** * Forget action * @OA\Post( - * path="/api/forget", + * path="/api/forget", * tags={"Authentication"}, * summary="Forget action", * operationId="forgetPassword", * @OA\RequestBody( + * required=true, * @OA\MediaType( - * mediaType="application/json", + * mediaType="application/json", * @OA\Schema( - * @OA\Property( - * property="username", - * type="string" - * ), + * required={"email"}, + * @OA\Property(property="email", type="string"), * example={"email": "mail@example.com"} * ) * ) @@ -241,18 +196,13 @@ abstract class OpenApiAuthController extends OpenApiController * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "message": "Check your email"} * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function forget(Request $request); @@ -260,31 +210,19 @@ abstract class OpenApiAuthController extends OpenApiController /** * Reset action * @OA\Post( - * path="/api/reset/{reset_token}", + * path="/api/reset/{token}", * tags={"Authentication"}, * summary="Reset action", * operationId="resetPassword", - * @OA\Parameter( - * name="reset_token", - * description="Reset token", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * @OA\Parameter(name="token", description="Reset token", required=true, in="path", @OA\Schema(type="string")), * @OA\RequestBody( + * required=true, * @OA\MediaType( * mediaType="application/json", * @OA\Schema( - * @OA\Property( - * property="password", - * type="string" - * ), - * @OA\Property( - * property="repeat_password", - * type="string" - * ), + * required={"password", "repeat_password"}, + * @OA\Property(property="password", type="string"), + * @OA\Property(property="repeat_password", type="string"), * example={"password": "password", "repeat_password": "password"} * ) * ) @@ -292,18 +230,19 @@ abstract class OpenApiAuthController extends OpenApiController * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "tokens": { + * "access_token": "base64-jwt-token", + * "refresh_token": "refresh-token" + * } + * } * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function reset(Request $request); @@ -311,37 +250,33 @@ abstract class OpenApiAuthController extends OpenApiController /** * Verify action * @OA\Post( - * path="/api/verify", + * path="/api/verify", * tags={"Authentication"}, * summary="Verify action", * operationId="accountVerify", * @OA\RequestBody( + * required=true, * @OA\MediaType( - * mediaType="application/json", + * mediaType="application/json", * @OA\Schema( - * @OA\Property( - * property="otp_code", - * type="string" - * ), - * example={"otp": "123456", "code": "otp_token"} + * required={"otp", "code"}, + * @OA\Property(property="otp", type="integer"), + * @OA\Property(property="code", type="string"), + * example={"otp": 123456, "code": "otp_token"} * ) * ) * ), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success"} * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function verify(Request $request); @@ -349,35 +284,25 @@ abstract class OpenApiAuthController extends OpenApiController /** * Resend action * @OA\Get( - * path="/api/resend/{otp_token}", + * path="/api/resend/{code}", * tags={"Authentication"}, * summary="Resend action", * operationId="resendOTP", - * @OA\Parameter( - * name="otp_token", - * description="OTP token", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * @OA\Parameter(name="code", description="OTP code", required=true, in="path", @OA\Schema(type="string")), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "code": "otp_token"} * ) * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function resend(); } + + diff --git a/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiCommentController.php.tpl b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiCommentController.php.tpl new file mode 100644 index 00000000..2321a8a9 --- /dev/null +++ b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiCommentController.php.tpl @@ -0,0 +1,95 @@ + + * @copyright Copyright (c) 2018 Softberg LLC (https://softberg.org) + * @link http://quantum.softberg.org/ + * @since 3.0.0 + */ + +namespace {{MODULE_NAMESPACE}}\Controllers\OpenApi; + +use Quantum\Http\Request; + +/** + * Class OpenApiCommentController + * @package Modules\Api + */ +abstract class OpenApiCommentController extends OpenApiController +{ + /** + * Create comment action + * @OA\Post( + * path="/api/comments/create/{uuid}", + * tags={"Comments"}, + * summary="Create comment action", + * operationId="createComment", + * security={{"bearer_token": {}}}, + * @OA\Parameter(name="uuid", description="Post UUID", required=true, in="path", @OA\Schema(type="string")), + * @OA\RequestBody( + * required=true, + * @OA\MediaType( + * mediaType="application/json", + * @OA\Schema( + * required={"content"}, + * @OA\Property(property="content", type="string"), + * example={"content": "Great post"} + * ) + * ) + * ), + * @OA\Response( + * response=200, + * description="Success", + * @OA\JsonContent( + * example={ + * "status": "success", + * "message": "Created successfully", + * "data": { + * "uuid": "40f0e8a0-bcd6-11ee-9c66-9f57d21b5b9f", + * "post_uuid": "4e9b8f47-bcd5-11ee-a0f2-fb642f7f26af", + * "user_uuid": "e31a9f20-bcd5-11ee-8fe4-a77a76ad48c2", + * "content": "Great post" + * } + * } + * ) + * ), + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") + * ) + */ + abstract public function create(Request $request, ?string $lang, string $uuid); + + /** + * Delete comment action + * @OA\Delete( + * path="/api/comments/delete/{uuid}", + * tags={"Comments"}, + * summary="Delete comment action", + * operationId="deleteComment", + * security={{"bearer_token": {}}}, + * @OA\Parameter(name="uuid", description="Comment UUID", required=true, in="path", @OA\Schema(type="string")), + * @OA\Response( + * response=200, + * description="Success", + * @OA\JsonContent( + * example={"status": "success", "message": "Deleted successfully"} + * ) + * ), + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") + * ) + */ + abstract public function delete(?string $lang, string $uuid); +} + + + diff --git a/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiPostController.php.tpl b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiPostController.php.tpl index bc9a7cde..38298475 100644 --- a/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiPostController.php.tpl +++ b/src/Module/Templates/DemoApi/src/Controllers/OpenApi/OpenApiPostController.php.tpl @@ -14,7 +14,6 @@ namespace {{MODULE_NAMESPACE}}\Controllers\OpenApi; -use Quantum\Http\Response; use Quantum\Http\Request; /** @@ -23,7 +22,6 @@ use Quantum\Http\Request; */ abstract class OpenApiPostController extends OpenApiController { - /** * Get posts action * @OA\Get( @@ -31,17 +29,36 @@ abstract class OpenApiPostController extends OpenApiController * tags={"Posts"}, * summary="Get posts action", * operationId="posts", + * @OA\Parameter(name="per_page", in="query", required=false, @OA\Schema(type="integer", default=8)), + * @OA\Parameter(name="page", in="query", required=false, @OA\Schema(type="integer", default=1)), + * @OA\Parameter(name="q", in="query", required=false, @OA\Schema(type="string")), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "data": { + * { + * "uuid": "4e9b8f47-bcd5-11ee-a0f2-fb642f7f26af", + * "title": "Demo Post", + * "content": "
Post content
", + * "image": "5d8f.../post-image.jpg", + * "date": "2026/05/14 10:30", + * "author": "Jon Smit" + * } + * }, + * "pagination": { + * "total_records": 10, + * "current_page": 1, + * "next_page": 2, + * "prev_page": null + * } + * } * ) * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function posts(Request $request); @@ -49,37 +66,46 @@ abstract class OpenApiPostController extends OpenApiController /** * Get post action * @OA\Get( - * path="/api/post/{id}", + * path="/api/post/{uuid}", * tags={"Posts"}, * summary="Get post action", * operationId="post", - * @OA\Parameter( - * name="id", - * description="Post Id", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * @OA\Parameter(name="uuid", description="Post UUID", required=true, in="path", @OA\Schema(type="string")), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "data": { + * "uuid": "4e9b8f47-bcd5-11ee-a0f2-fb642f7f26af", + * "title": "Demo Post", + * "content": "Post content
", + * "image": "5d8f.../post-image.jpg", + * "date": "2026/05/14 10:30", + * "author": "Jon Smit", + * "comments": { + * { + * "uuid": "40f0e8a0-bcd6-11ee-9c66-9f57d21b5b9f", + * "author": { + * "firstname": "Jane", + * "lastname": "Doe", + * "image": "e31a.../avatar.png" + * }, + * "content": "Great post", + * "date": "2026-05-14 10:35" + * } + * } + * } + * } * ) * ), - * @OA\Response( - * response=404, - * description="Not Found" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=404, description="Not Found"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ - abstract public function post(?string $lang, string $postId); + abstract public function post(?string $lang, string $uuid); /** * Get my posts action @@ -88,24 +114,29 @@ abstract class OpenApiPostController extends OpenApiController * tags={"Posts"}, * summary="Get my posts action", * operationId="myPosts", - * security={ - * {"bearer_token": {}} - * }, + * security={{"bearer_token": {}}}, * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "data": { + * { + * "uuid": "4e9b8f47-bcd5-11ee-a0f2-fb642f7f26af", + * "title": "My Post", + * "content": "Post content
", + * "image": "5d8f.../post-image.jpg", + * "date": "2026/05/14 10:30", + * "author": "Jon Smit" + * } + * } + * } * ) * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function myPosts(); @@ -113,53 +144,46 @@ abstract class OpenApiPostController extends OpenApiController /** * Create post action * @OA\Post( - * path="/api/my-posts/create", + * path="/api/my-posts/create", * tags={"Posts"}, * summary="Create post action", * operationId="create", - * security={ - * {"bearer_token": {} - * }}, + * security={{"bearer_token": {}}}, * @OA\RequestBody( + * required=true, * @OA\MediaType( * mediaType="multipart/form-data", - * @OA\Schema( - * type="object", - * required={"title", "content"}, - * @OA\Property( - * property="title", - * type="string", - * ), - * @OA\Property( - * property="content", - * type="string", - * ), - * @OA\Property( - * property="image", - * type="file", - * ) - * ) + * @OA\Schema( + * type="object", + * required={"title", "content"}, + * @OA\Property(property="title", type="string"), + * @OA\Property(property="content", type="string"), + * @OA\Property(property="image", type="string", format="binary") * ) + * ) * ), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "message": "Created successfully", + * "data": { + * "uuid": "4e9b8f47-bcd5-11ee-a0f2-fb642f7f26af", + * "title": "Created Post", + * "content": "Post content
", + * "image": "5d8f.../post-image.jpg", + * "date": "2026/05/14 10:30", + * "author": "Jon Smit" + * } + * } * ) * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ abstract public function create(Request $request); @@ -167,148 +191,98 @@ abstract class OpenApiPostController extends OpenApiController /** * Amend post action * @OA\Put( - * path="/api/my-posts/amend/{id}", + * path="/api/my-posts/amend/{uuid}", * tags={"Posts"}, * summary="Amend post action", * operationId="amend", - * security={ - * {"bearer_token": {} - * }}, - * @OA\Parameter( - * name="id", - * description="Post id", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * security={{"bearer_token": {}}}, + * @OA\Parameter(name="uuid", description="Post UUID", required=true, in="path", @OA\Schema(type="string")), * @OA\RequestBody( + * required=true, * @OA\MediaType( * mediaType="multipart/form-data", * @OA\Schema( * type="object", * required={"title", "content"}, - * @OA\Property( - * property="title", - * type="string", - * ), - * @OA\Property( - * property="content", - * type="string", - * ), - * @OA\Property( - * property="image", - * type="file", - * ) - * ) + * @OA\Property(property="title", type="string"), + * @OA\Property(property="content", type="string"), + * @OA\Property(property="image", type="string", format="binary") + * ) * ) * ), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={ + * "status": "success", + * "message": "Updated successfully", + * "data": { + * "uuid": "4e9b8f47-bcd5-11ee-a0f2-fb642f7f26af", + * "title": "Updated Post", + * "content": "Updated content
", + * "image": "5d8f.../post-image.jpg", + * "date": "2026/05/14 11:00", + * "author": "Jon Smit" + * } + * } * ) * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ - abstract public function amend(Request $request, ?string $lang, string $postId); + abstract public function amend(Request $request, ?string $lang, string $uuid); /** * Delete post action * @OA\Delete( - * path="/api/my-posts/delete/{id}", + * path="/api/my-posts/delete/{uuid}", * tags={"Posts"}, * summary="Delete post action", * operationId="delete", - * security={ - * {"bearer_token": {}} - * }, - * @OA\Parameter( - * name="id", - * description="Post id", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * security={{"bearer_token": {}}}, + * @OA\Parameter(name="uuid", description="Post UUID", required=true, in="path", @OA\Schema(type="string")), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "message": "Deleted successfully"} * ) * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ - abstract public function delete(?string $lang, string $postId); + abstract public function delete(?string $lang, string $uuid); /** * Delete post image action * @OA\Delete( - * path="/api/my-posts/delete-image/{id}", + * path="/api/my-posts/delete-image/{uuid}", * tags={"Posts"}, * summary="Delete post image action", * operationId="deleteImage", - * security={ - * {"bearer_token": {} - * }}, - * @OA\Parameter( - * name="id", - * description="Post id", - * required=true, - * in="path", - * @OA\Schema( - * type="string" - * ) - * ), + * security={{"bearer_token": {}}}, + * @OA\Parameter(name="uuid", description="Post UUID", required=true, in="path", @OA\Schema(type="string")), * @OA\Response( * response=200, * description="Success", - * @OA\MediaType( - * mediaType="application/json", + * @OA\JsonContent( + * example={"status": "success", "message": "Deleted successfully"} * ) * ), - * @OA\Response( - * response=401, - * description="Unauthorized Request" - * ), - * @OA\Response( - * response=422, - * description="Unprocessable Entity" - * ), - * @OA\Response( - * response=500, - * description="Internal Server Error" - * ) + * @OA\Response(response=401, description="Unauthorized Request"), + * @OA\Response(response=422, description="Unprocessable Entity"), + * @OA\Response(response=429, description="Too Many Requests"), + * @OA\Response(response=500, description="Internal Server Error") * ) */ - abstract public function deleteImage(?string $lang, string $postId); - + abstract public function deleteImage(?string $lang, string $uuid); } + + diff --git a/tests/Unit/Console/Commands/OpenApiCommandTest.php b/tests/Unit/Console/Commands/OpenApiCommandTest.php index 641fd269..cfe6db7c 100644 --- a/tests/Unit/Console/Commands/OpenApiCommandTest.php +++ b/tests/Unit/Console/Commands/OpenApiCommandTest.php @@ -135,10 +135,8 @@ public function testOpenapiRoutesContainsModuleSpecPath(): void $this->assertStringContainsString('"openapi"', $routes); $this->assertStringContainsString('Blog', $routes); - $this->assertTrue( - strpos($routes, 'resources/openapi/spec.json') !== false - || strpos($routes, 'resources\\openapi\\spec.json') !== false - ); + $this->assertStringContainsString('modules_dir() . DS . "Blog"', $routes); + $this->assertStringContainsString('. DS . "resources" . DS . "openapi" . DS . "spec.json"', $routes); } public function testCopyResourcesSkipsExcludedFiles(): void