From 5ab8af6bef11399f6ed0b59249c1f1c125c3742a Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Mon, 29 Sep 2025 14:52:44 -0300 Subject: [PATCH 1/3] feat: Add OpenAPI documentation to "getAll" method --- .../Apis/LanguagesApiController.php | 53 +++++++++++++++++-- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Apis/LanguagesApiController.php b/app/Http/Controllers/Apis/LanguagesApiController.php index ecf4d9896..850f1155e 100644 --- a/app/Http/Controllers/Apis/LanguagesApiController.php +++ b/app/Http/Controllers/Apis/LanguagesApiController.php @@ -12,9 +12,11 @@ * limitations under the License. **/ use App\Models\Foundation\Main\Repositories\ILanguageRepository; +use Illuminate\Http\Response; use Illuminate\Support\Facades\Log; use models\exceptions\EntityNotFoundException; use models\exceptions\ValidationException; +use OpenApi\Attributes as OA; use utils\PagingResponse; use Illuminate\Support\Facades\Request; /** @@ -37,9 +39,52 @@ public function __construct(ILanguageRepository $language_repository) $this->language_repository = $language_repository; } - /** - * @return mixed - */ + #[OA\Get( + path: "/api/v1/languages", + description: "Get all available languages with ISO codes", + summary: 'Get all languages', + operationId: 'getAllLanguages', + tags: ['Languages'], + parameters: [ + new OA\Parameter( + name: 'expand', + in: 'query', + required: false, + description: 'Parameter for expanding related entity properties through serialization. Note: Has no effect on this endpoint since languages are returned as simple arrays, not complex entities. Always returns iso_code and name regardless of this parameter.', + schema: new OA\Schema(type: 'string', example: '') + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Success - Returns paginated list of languages', + content: new OA\JsonContent( + properties: [ + 'total' => new OA\Property(property: 'total', type: 'integer', example: 50), + 'per_page' => new OA\Property(property: 'per_page', type: 'integer', example: 50), + 'current_page' => new OA\Property(property: 'current_page', type: 'integer', example: 1), + 'last_page' => new OA\Property(property: 'last_page', type: 'integer', example: 1), + 'data' => new OA\Property( + property: 'data', + type: 'array', + items: new OA\Items( + properties: [ + 'id' => new OA\Property(property: 'id', type: 'integer', example: 1), + 'name' => new OA\Property(property: 'name', type: 'string', example: 'English'), + 'iso_code' => new OA\Property(property: 'iso_code', type: 'string', example: 'en') + ], + type: 'object' + ) + ) + ], + type: 'object' + ) + ), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error") + ] + )] public function getAll(){ try { $languages = $this->language_repository->getAll(); @@ -68,4 +113,4 @@ public function getAll(){ return $this->error500($ex); } } -} \ No newline at end of file +} From 2bc954813892f8a4d800fd0baa791aa619fe6f81 Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Mon, 29 Sep 2025 15:03:13 -0300 Subject: [PATCH 2/3] fix: Open API path to endpoint --- app/Http/Controllers/Apis/LanguagesApiController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Http/Controllers/Apis/LanguagesApiController.php b/app/Http/Controllers/Apis/LanguagesApiController.php index 850f1155e..119ed650c 100644 --- a/app/Http/Controllers/Apis/LanguagesApiController.php +++ b/app/Http/Controllers/Apis/LanguagesApiController.php @@ -40,7 +40,7 @@ public function __construct(ILanguageRepository $language_repository) } #[OA\Get( - path: "/api/v1/languages", + path: "/api/public/v1/languages", description: "Get all available languages with ISO codes", summary: 'Get all languages', operationId: 'getAllLanguages', From 7e56225d24baa2ab812652cf5285e6c9fd4af8bf Mon Sep 17 00:00:00 2001 From: Matias Perrone Date: Wed, 1 Oct 2025 15:15:06 -0300 Subject: [PATCH 3/3] fix: Reuse already defined schema and add Paginated Schema --- .../Apis/LanguagesApiController.php | 63 +++---------------- app/Swagger/Countries.php | 4 +- app/Swagger/Languages.php | 32 ++++++++++ start_local_server.sh | 3 +- 4 files changed, 46 insertions(+), 56 deletions(-) create mode 100644 app/Swagger/Languages.php diff --git a/app/Http/Controllers/Apis/LanguagesApiController.php b/app/Http/Controllers/Apis/LanguagesApiController.php index 119ed650c..302ae4f1f 100644 --- a/app/Http/Controllers/Apis/LanguagesApiController.php +++ b/app/Http/Controllers/Apis/LanguagesApiController.php @@ -13,18 +13,15 @@ **/ use App\Models\Foundation\Main\Repositories\ILanguageRepository; use Illuminate\Http\Response; -use Illuminate\Support\Facades\Log; -use models\exceptions\EntityNotFoundException; -use models\exceptions\ValidationException; use OpenApi\Attributes as OA; use utils\PagingResponse; -use Illuminate\Support\Facades\Request; /** * Class LanguagesApiController * @package App\Http\Controllers */ final class LanguagesApiController extends JsonController { + use RequestProcessor; /** * @var ILanguageRepository */ @@ -45,50 +42,22 @@ public function __construct(ILanguageRepository $language_repository) summary: 'Get all languages', operationId: 'getAllLanguages', tags: ['Languages'], - parameters: [ - new OA\Parameter( - name: 'expand', - in: 'query', - required: false, - description: 'Parameter for expanding related entity properties through serialization. Note: Has no effect on this endpoint since languages are returned as simple arrays, not complex entities. Always returns iso_code and name regardless of this parameter.', - schema: new OA\Schema(type: 'string', example: '') - ), - ], responses: [ new OA\Response( response: 200, description: 'Success - Returns paginated list of languages', - content: new OA\JsonContent( - properties: [ - 'total' => new OA\Property(property: 'total', type: 'integer', example: 50), - 'per_page' => new OA\Property(property: 'per_page', type: 'integer', example: 50), - 'current_page' => new OA\Property(property: 'current_page', type: 'integer', example: 1), - 'last_page' => new OA\Property(property: 'last_page', type: 'integer', example: 1), - 'data' => new OA\Property( - property: 'data', - type: 'array', - items: new OA\Items( - properties: [ - 'id' => new OA\Property(property: 'id', type: 'integer', example: 1), - 'name' => new OA\Property(property: 'name', type: 'string', example: 'English'), - 'iso_code' => new OA\Property(property: 'iso_code', type: 'string', example: 'en') - ], - type: 'object' - ) - ) - ], - type: 'object' - ) + content: new OA\JsonContent(ref: '#/components/schemas/PaginatedISOLanguageElementResponseSchema'), ), new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error") ] )] - public function getAll(){ - try { - $languages = $this->language_repository->getAll(); - $response = new PagingResponse + public function getAll() + { + return $this->processRequest(function () { + $languages = $this->language_repository->getAll(); + $response = new PagingResponse ( count($languages), count($languages), @@ -97,20 +66,8 @@ public function getAll(){ $languages ); - return $this->ok($response->toArray($expand = Request::input('expand',''))); - } - catch (ValidationException $ex1) { - Log::warning($ex1); - return $this->error412(array($ex1->getMessage())); - } - catch(EntityNotFoundException $ex2) - { - Log::warning($ex2); - return $this->error404(array('message'=> $ex2->getMessage())); - } - catch (\Exception $ex) { - Log::error($ex); - return $this->error500($ex); - } + return $this->ok($response->toArray()); + }); } + } diff --git a/app/Swagger/Countries.php b/app/Swagger/Countries.php index 49ecc8275..496dbdd41 100644 --- a/app/Swagger/Countries.php +++ b/app/Swagger/Countries.php @@ -10,7 +10,7 @@ 'name' => new OA\Property(property: 'name', type: 'string', example: 'United States') ] )] -class ISOElementSchema {}; +class ISOCountryElementSchema {}; #[OA\Schema( schema: 'PaginatedISOCountryElementResponseSchema', @@ -29,4 +29,4 @@ class ISOElementSchema {}; ) ] )] -class PaginatedISOElementResponseSchema {}; +class PaginatedISOCountryElementResponseSchema {}; diff --git a/app/Swagger/Languages.php b/app/Swagger/Languages.php new file mode 100644 index 000000000..4f7ed22df --- /dev/null +++ b/app/Swagger/Languages.php @@ -0,0 +1,32 @@ + new OA\Property(property: 'iso_code', type: 'string', example: 'US'), + 'name' => new OA\Property(property: 'name', type: 'string', example: 'United States') + ] +)] +class ISOLanguageElementSchema {}; + +#[OA\Schema( + schema: 'PaginatedISOLanguageElementResponseSchema', + type: 'object', + allOf: [ + new OA\Schema(ref: '#/components/schemas/PaginateDataSchemaResponse'), + new OA\Schema( + type: 'object', + properties: [ + new OA\Property( + property: 'data', + type: 'array', + items: new OA\Items(ref: "#/components/schemas/ISOLanguageElementSchema") + ) + ] + ) + ] +)] +class PaginatedISOLanguageElementResponseSchema {}; diff --git a/start_local_server.sh b/start_local_server.sh index b8bf86523..b13a06679 100755 --- a/start_local_server.sh +++ b/start_local_server.sh @@ -6,6 +6,7 @@ export DOCKER_SCAN_SUGGEST=false docker compose up -d app # Run all setup commands inside the running container docker compose exec app composer install +docker compose exec app composer dump-autoload -o docker compose exec app php artisan db:create_test_db --schema=config docker compose exec app php artisan db:create_test_db --schema=model docker compose exec app php artisan doctrine:migrations:migrate --no-interaction --em=config @@ -17,4 +18,4 @@ docker compose exec app php artisan l5-swagger:generate # Now bring up all remaining services docker compose up -d # Open shell as appuser -docker compose exec app /bin/bash \ No newline at end of file +docker compose exec app /bin/bash