diff --git a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeFeatureTypeApiController.php b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeFeatureTypeApiController.php index e2bfadae7..8d0c8ee5c 100644 --- a/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeFeatureTypeApiController.php +++ b/app/Http/Controllers/Apis/Protected/Summit/OAuth2SummitBadgeFeatureTypeApiController.php @@ -1,4 +1,7 @@ -repository = $repository; $this->summit_repository = $summit_repository; $this->service = $service; } + // OpenAPI Documentation + + #[OA\Get( + path: '/api/v1/summits/{id}/badge-feature-types', + operationId: 'getAllBadgeFeatureTypes', + summary: 'Get all badge feature types for a summit', + description: 'Retrieves a paginated list of badge feature types for a specific summit. Badge feature types define visual elements and features that can be applied to attendee badges (e.g., speaker ribbons, sponsor logos, special access indicators).', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::ReadSummitData, + SummitScopes::ReadAllSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + new OA\Parameter( + name: 'page', + in: 'query', + required: false, + description: 'Page number for pagination', + schema: new OA\Schema(type: 'integer', example: 1) + ), + new OA\Parameter( + name: 'per_page', + in: 'query', + required: false, + description: 'Items per page', + schema: new OA\Schema(type: 'integer', example: 10, maximum: 100) + ), + new OA\Parameter( + name: 'filter[]', + in: 'query', + required: false, + description: 'Filter expressions. Format: fieldvalue. Available field: name (=@, ==). Operators: == (equals), =@ (starts with)', + style: 'form', + explode: true, + schema: new OA\Schema( + type: 'array', + items: new OA\Items(type: 'string', example: 'name@@speaker') + ) + ), + new OA\Parameter( + name: 'order', + in: 'query', + required: false, + description: 'Order by field(s). Available fields: name, id. Use "-" prefix for descending order.', + schema: new OA\Schema(type: 'string', example: 'name') + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Badge feature types retrieved successfully', + content: new OA\JsonContent(ref: '#/components/schemas/PaginatedSummitBadgeFeatureTypesResponse') + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + + #[OA\Get( + path: '/api/v1/summits/{id}/badge-feature-types/{feature_id}', + operationId: 'getBadgeFeatureType', + summary: 'Get a badge feature type by ID', + description: 'Retrieves detailed information about a specific badge feature type.', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::ReadSummitData, + SummitScopes::ReadAllSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + new OA\Parameter( + name: 'feature_id', + in: 'path', + required: true, + description: 'Badge Feature Type ID', + schema: new OA\Schema(type: 'integer') + ), + ], + responses: [ + new OA\Response( + response: 200, + description: 'Badge feature type retrieved successfully', + content: new OA\JsonContent(ref: '#/components/schemas/SummitBadgeFeatureType') + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + + #[OA\Post( + path: '/api/v1/summits/{id}/badge-feature-types', + operationId: 'createBadgeFeatureType', + summary: 'Create a new badge feature type', + description: 'Creates a new badge feature type for the summit.', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::WriteSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + ], + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent(ref: '#/components/schemas/SummitBadgeFeatureTypeCreateRequest') + ), + responses: [ + new OA\Response( + response: 201, + description: 'Badge feature type created successfully', + content: new OA\JsonContent(ref: '#/components/schemas/SummitBadgeFeatureType') + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_UNPROCESSABLE_ENTITY, description: "Unprocessable Entity"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + + #[OA\Put( + path: '/api/v1/summits/{id}/badge-feature-types/{feature_id}', + operationId: 'updateBadgeFeatureType', + summary: 'Update a badge feature type', + description: 'Updates an existing badge feature type.', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::WriteSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + new OA\Parameter( + name: 'feature_id', + in: 'path', + required: true, + description: 'Badge Feature Type ID', + schema: new OA\Schema(type: 'integer') + ), + ], + requestBody: new OA\RequestBody( + required: true, + content: new OA\JsonContent(ref: '#/components/schemas/SummitBadgeFeatureTypeUpdateRequest') + ), + responses: [ + new OA\Response( + response: 200, + description: 'Badge feature type updated successfully', + content: new OA\JsonContent(ref: '#/components/schemas/SummitBadgeFeatureType') + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_UNPROCESSABLE_ENTITY, description: "Unprocessable Entity"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + + #[OA\Delete( + path: '/api/v1/summits/{id}/badge-feature-types/{feature_id}', + operationId: 'deleteBadgeFeatureType', + summary: 'Delete a badge feature type', + description: 'Deletes an existing badge feature type from the summit.', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::WriteSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + new OA\Parameter( + name: 'feature_id', + in: 'path', + required: true, + description: 'Badge Feature Type ID', + schema: new OA\Schema(type: 'integer') + ), + ], + responses: [ + new OA\Response( + response: 204, + description: 'Badge feature type deleted successfully' + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + + #[OA\Post( + path: '/api/v1/summits/{id}/badge-feature-types/{feature_id}/image', + operationId: 'addBadgeFeatureTypeImage', + summary: 'Add an image to a badge feature type', + description: 'Uploads and associates an image file with a badge feature type. This image is typically displayed on attendee badges.', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::WriteSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + new OA\Parameter( + name: 'feature_id', + in: 'path', + required: true, + description: 'Badge Feature Type ID', + schema: new OA\Schema(type: 'integer') + ), + ], + requestBody: new OA\RequestBody( + required: true, + content: new OA\MediaType( + mediaType: 'multipart/form-data', + schema: new OA\Schema( + required: ['file'], + properties: [ + new OA\Property( + property: 'file', + type: 'string', + format: 'binary', + description: 'Image file to upload' + ) + ] + ) + ) + ), + responses: [ + new OA\Response( + response: 201, + description: 'Image uploaded successfully', + content: new OA\JsonContent( + type: 'object', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1), + new OA\Property(property: 'url', type: 'string', example: 'https://example.com/images/badge-feature.png'), + ] + ) + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] + + #[OA\Delete( + path: '/api/v1/summits/{id}/badge-feature-types/{feature_id}/image', + operationId: 'deleteBadgeFeatureTypeImage', + summary: 'Delete the image from a badge feature type', + description: 'Removes the associated image from a badge feature type.', + x: [ + 'required-groups' => [ + IGroup::SuperAdmins, + IGroup::Administrators, + IGroup::SummitAdministrators, + IGroup::SummitRegistrationAdmins, + ] + ], + security: [ + [ + 'badge_feature_types_oauth2' => [ + SummitScopes::WriteSummitData, + ] + ] + ], + tags: ['Badge Feature Types'], + parameters: [ + new OA\Parameter( + name: 'id', + in: 'path', + required: true, + description: 'Summit ID', + schema: new OA\Schema(type: 'integer') + ), + new OA\Parameter( + name: 'feature_id', + in: 'path', + required: true, + description: 'Badge Feature Type ID', + schema: new OA\Schema(type: 'integer') + ), + ], + responses: [ + new OA\Response( + response: 204, + description: 'Image deleted successfully' + ), + new OA\Response(response: Response::HTTP_BAD_REQUEST, description: "Bad Request"), + new OA\Response(response: Response::HTTP_UNAUTHORIZED, description: "Unauthorized"), + new OA\Response(response: Response::HTTP_FORBIDDEN, description: "Forbidden"), + new OA\Response(response: Response::HTTP_NOT_FOUND, description: "Not Found"), + new OA\Response(response: Response::HTTP_PRECONDITION_FAILED, description: "Validation Error"), + new OA\Response(response: Response::HTTP_INTERNAL_SERVER_ERROR, description: "Server Error"), + ] + )] /** * @return array */ - protected function getFilterRules():array + protected function getFilterRules(): array { return [ 'name' => ['=@', '=='], @@ -77,7 +500,8 @@ protected function getFilterRules():array /** * @return array */ - protected function getFilterValidatorRules():array{ + protected function getFilterValidatorRules(): array + { return [ 'name' => 'sometimes|required|string', ]; @@ -85,7 +509,8 @@ protected function getFilterValidatorRules():array{ /** * @return array */ - protected function getOrderRules():array{ + protected function getOrderRules(): array + { return [ 'id', 'name', @@ -108,7 +533,7 @@ protected function getOrderRules():array{ */ function getAddValidationRules(array $payload): array { - return SummitBadgeFeatureTypeValidationRulesFactory::build($payload); + return SummitBadgeFeatureTypeValidationRulesFactory::build($payload); } /** @@ -126,7 +551,7 @@ protected function addChild(Summit $summit, array $payload): IEntity */ protected function getSummitRepository(): ISummitRepository { - return $this->summit_repository; + return $this->summit_repository; } /** @@ -152,7 +577,7 @@ protected function getRepository(): IBaseRepository */ protected function deleteChild(Summit $summit, $child_id): void { - $this->service->deleteBadgeFeatureType($summit, $child_id); + $this->service->deleteBadgeFeatureType($summit, $child_id); } /** @@ -160,9 +585,9 @@ protected function deleteChild(Summit $summit, $child_id): void * @param $child_id * @return IEntity|null */ - protected function getChildFromSummit(Summit $summit,$child_id): ?IEntity + protected function getChildFromSummit(Summit $summit, $child_id): ?IEntity { - return $summit->getFeatureTypeById($child_id); + return $summit->getFeatureTypeById($child_id); } /** @@ -191,10 +616,12 @@ protected function updateChild(Summit $summit, int $child_id, array $payload): I * @param $feature_id * @return \Illuminate\Http\JsonResponse|mixed */ - public function addFeatureImage(LaravelRequest $request, $summit_id, $feature_id){ + public function addFeatureImage(LaravelRequest $request, $summit_id, $feature_id) + { try { $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->resource_server_context)->find($summit_id); - if (is_null($summit)) return $this->error404(); + if (is_null($summit)) + return $this->error404(); $file = $request->file('file'); if (is_null($file)) { @@ -205,18 +632,13 @@ public function addFeatureImage(LaravelRequest $request, $summit_id, $feature_id return $this->created(SerializerRegistry::getInstance()->getSerializer($image)->serialize()); - } - catch (ValidationException $ex1) - { + } catch (ValidationException $ex1) { Log::warning($ex1); return $this->error412(array($ex1->getMessage())); - } - catch(EntityNotFoundException $ex2) - { + } catch (EntityNotFoundException $ex2) { Log::warning($ex2); - return $this->error404(array('message'=> $ex2->getMessage())); - } - catch (Exception $ex) { + return $this->error404(array('message' => $ex2->getMessage())); + } catch (Exception $ex) { Log::error($ex); return $this->error500($ex); } @@ -227,24 +649,21 @@ public function addFeatureImage(LaravelRequest $request, $summit_id, $feature_id * @param $feature_id * @return \Illuminate\Http\JsonResponse|mixed */ - public function deleteFeatureImage($summit_id, $feature_id) { + public function deleteFeatureImage($summit_id, $feature_id) + { try { $summit = SummitFinderStrategyFactory::build($this->getSummitRepository(), $this->resource_server_context)->find($summit_id); - if (is_null($summit)) return $this->error404(); + if (is_null($summit)) + return $this->error404(); $this->service->removeFeatureImage($summit, $feature_id); return $this->deleted(); - } - catch (ValidationException $ex1) - { + } catch (ValidationException $ex1) { Log::warning($ex1); return $this->error412(array($ex1->getMessage())); - } - catch(EntityNotFoundException $ex2) - { + } catch (EntityNotFoundException $ex2) { Log::warning($ex2); - return $this->error404(array('message'=> $ex2->getMessage())); - } - catch (Exception $ex) { + return $this->error404(array('message' => $ex2->getMessage())); + } catch (Exception $ex) { Log::error($ex); return $this->error500($ex); } diff --git a/app/Swagger/Security/BadgeFeatureTypesOauth2Schema.php b/app/Swagger/Security/BadgeFeatureTypesOauth2Schema.php new file mode 100644 index 000000000..1ee782e02 --- /dev/null +++ b/app/Swagger/Security/BadgeFeatureTypesOauth2Schema.php @@ -0,0 +1,25 @@ + 'Read All Summit Data', + SummitScopes::ReadSummitData => 'Read Summit Data', + SummitScopes::WriteSummitData => 'Write Summit Data', + ], + ), + ], + ) +] +class BadgeFeatureTypesOauth2Schema{} diff --git a/app/Swagger/SummitRegistrationSchemas.php b/app/Swagger/SummitRegistrationSchemas.php index 6b3e2f895..80812cf41 100644 --- a/app/Swagger/SummitRegistrationSchemas.php +++ b/app/Swagger/SummitRegistrationSchemas.php @@ -5,3 +5,60 @@ use OpenApi\Attributes as OA; // + +// Summit Badge Feature Types + +#[OA\Schema( + schema: 'SummitBadgeFeatureType', + type: 'object', + properties: [ + new OA\Property(property: 'id', type: 'integer', example: 1), + new OA\Property(property: 'name', type: 'string', example: 'Speaker Ribbon'), + new OA\Property(property: 'description', type: 'string', nullable: true, example: 'Special ribbon indicating speaker status'), + new OA\Property(property: 'template_content', type: 'string', nullable: true, example: '
{{name}}
'), + new OA\Property(property: 'summit_id', type: 'integer', example: 42), + new OA\Property(property: 'image', type: 'string', nullable: true, example: 'https://example.com/images/speaker-ribbon.png'), + ] +)] +class SummitBadgeFeatureTypeSchema {} + +#[OA\Schema( + schema: 'PaginatedSummitBadgeFeatureTypesResponse', + 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/SummitBadgeFeatureType') + ) + ] + ) + ] +)] +class PaginatedSummitBadgeFeatureTypesResponseSchema {} + +#[OA\Schema( + schema: 'SummitBadgeFeatureTypeCreateRequest', + type: 'object', + required: ['name'], + properties: [ + new OA\Property(property: 'name', type: 'string', example: 'Speaker Ribbon'), + new OA\Property(property: 'description', type: 'string', nullable: true, example: 'Special ribbon for speakers'), + new OA\Property(property: 'template_content', type: 'string', nullable: true, example: '
{{name}}
'), + ] +)] +class SummitBadgeFeatureTypeCreateRequestSchema {} + +#[OA\Schema( + schema: 'SummitBadgeFeatureTypeUpdateRequest', + type: 'object', + properties: [ + new OA\Property(property: 'name', type: 'string', example: 'VIP Ribbon'), + new OA\Property(property: 'description', type: 'string', nullable: true, example: 'VIP attendee designation'), + new OA\Property(property: 'template_content', type: 'string', nullable: true, example: '
{{name}}
'), + ] +)] +class SummitBadgeFeatureTypeUpdateRequestSchema {} diff --git a/app/Swagger/schemas.php b/app/Swagger/schemas.php index 1eff77226..b1e2f5134 100644 --- a/app/Swagger/schemas.php +++ b/app/Swagger/schemas.php @@ -346,7 +346,7 @@ class RSVPUpdateRequestSchema_{ type: 'object', properties: [ new OA\Property(property: 'attendee_id', type: 'integer', example: 123), - new OA\Property(property: 'seet_type', type: 'string', example: RSVP::SeatTypeRegular), + new OA\Property(property: 'seat_type', type: 'string', example: RSVP::SeatTypeRegular), ] )]