Skip to content

Conversation

@TatevikGr
Copy link
Contributor

@TatevikGr TatevikGr commented Nov 21, 2025

Summary by CodeRabbit

  • API Changes

    • Reorganized administrator attribute endpoints under a clearer /administrators/{id}/attributes structure.
    • Standardized path parameter names to adminId and removed several exposed numeric ID fields from request payloads.
  • Bug Fixes

    • Consistent 404 responses when campaigns or related resources are not found.
  • Documentation

    • OpenAPI docs updated with new paths and improved schema references for template and message endpoints.

✏️ Tip: You can customize this high-level summary in your review settings.

Thanks for contributing to phpList!

@coderabbitai
Copy link

coderabbitai bot commented Nov 21, 2025

Warning

Rate limit exceeded

@TatevikGr has exceeded the limit for the number of commits or files that can be reviewed per hour. Please wait 8 minutes and 5 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between ccfc48e and bfdaa4b.

📒 Files selected for processing (1)
  • src/Messaging/Request/CreateTemplateRequest.php (1 hunks)

Note

.coderabbit.yaml has unrecognized properties

CodeRabbit is using all valid settings from your configuration. Unrecognized properties (listed below) have been ignored and may indicate typos or deprecated fields that can be removed.

⚠️ Parsing warnings (1)
Validation error: Unrecognized key(s) in object: 'checks'
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json
📝 Walkthrough

Walkthrough

This PR makes multiple coordinated API and request-shape changes: removes runtime integer casting of some route params in the request validator; moves admin attribute-value routes from /administrators/attribute-values to nested /administrators/{adminId}/attributes/{definitionId} (and updates OpenAPI docs and tests); renames route parameter mappings from administratorId → adminId in AdministratorController MapEntity attributes; removes ID properties from several Request classes (administratorId, messageId, subscriberId) and their DTO construction; switches several service/controller calls to use named arguments; adds explicit 404 guards and OpenAPI 404 responses to Messaging campaign endpoints; augments CreateTemplateRequest with OpenAPI schema, new properties, and a getDto implementation; and removes an entity deletion+flush from getAttributeDefinition.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant Router as Router
  participant AdminAttrCtrl as AdminAttributeValueController
  participant Auth as AuthListener
  participant AttrService as AttributeService
  Note over AdminAttrCtrl: Route prefix changed: /administrators -> endpoints now under /administrators/{adminId}/attributes
  Client->>Router: HTTP POST /api/v2/administrators/{adminId}/attributes/{definitionId}
  Router->>AdminAttrCtrl: dispatch with route params (adminId, definitionId)
  AdminAttrCtrl->>AttrService: handle create/update/list (uses named args for provider)
  AttrService-->>AdminAttrCtrl: response
  AdminAttrCtrl-->>Client: HTTP 200/201
Loading
sequenceDiagram
  participant Client as Client
  participant Router as Router
  participant CampaignCtrl as CampaignController
  participant MapEntity as MapEntityResolver
  participant Auth as AuthListener
  participant SyncProc as SyncCampaignProcessor
  Note over CampaignCtrl: New early 404 guard for mapped Message
  Client->>Router: GET /api/v2/campaigns/{messageId}
  Router->>MapEntity: map messageId -> Message|null
  MapEntity-->>CampaignCtrl: Message|null
  alt Message == null
    CampaignCtrl-->>Client: HTTP 404 "Campaign not found."
  else Message != null
    CampaignCtrl->>Auth: authenticate/authorize
    Auth-->>CampaignCtrl: ok
    CampaignCtrl-->>Client: HTTP 200 with payload
  end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

  • Areas needing extra attention:
    • AdminAttributeValueController routing and OpenAPI updates — ensure routing prefixes, route names, and generated docs all align and tests updated accordingly (tests changed too).
    • MapEntity parameter renames (administratorId → adminId) — confirm no residual references remain and generated route parameter docs match.
    • Removal of ID properties from request classes and DTO construction — verify downstream services and DTO consumers do not rely on those removed fields.
    • Named-argument migrations — check target methods accept named parameters (signature compatibility) and static analysis/type checks.
    • Behavioral changes: removal of deletion+flush in getAttributeDefinition and added 404 guards in CampaignController — review for side effects and consistency with business rules.

Possibly related PRs

  • Refactor attribute definition request handling #161 — touches admin attribute controllers and attribute deletion behavior; likely overlaps on routing and attribute handling.
  • Dev #159 — modifies the same AdminAttributeValueController class and previously introduced EntityManager flush calls; high potential for conflict with removed deletion/flush.

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Refactor/admin attributes routes' clearly describes the main change: refactoring admin attributes API routes to use a new /attributes namespace structure.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
src/Subscription/Controller/ListMembersController.php (1)

125-127: Fix the OpenAPI path and parameter type in getSubscribersCount

Both issues are real:

  1. Line 127: OA path /api/v2/lists/{listId}/count should include /subscribers to match the actual route at line 125: /api/v2/lists/{listId}/subscribers/count

  2. Line 145: listId parameter type is 'string' but should be 'integer' to match the first endpoint (line 52) and the numeric route requirement requirements: ['listId' => '\d+']

src/Identity/Controller/AdminAttributeValueController.php (1)

293-367: Fix wrong entity mapping/type and handle missing attribute in getAttributeDefinition

Here there are two coupled issues:

  1. The admin parameter is mapped as an AdminAttributeDefinition instead of an Administrator, while using adminId from the path. This will hydrate the wrong entity type and can easily lead to incorrect IDs being passed into getAdminAttribute or subtle failures.
  2. getAdminAttribute(...) can return null (see the explicit null-check in delete()), but here its result is passed straight into the normalizer without a guard. That can yield a 500 or a misleading 200 with empty data instead of the documented 404.

Consider tightening this endpoint as follows.

-    public function getAttributeDefinition(
-        Request $request,
-        #[MapEntity(mapping: ['adminId' => 'id'])] ?AdminAttributeDefinition $admin,
-        #[MapEntity(mapping: ['definitionId' => 'id'])] ?AdminAttributeDefinition $definition,
-    ): JsonResponse {
+    public function getAttributeDefinition(
+        Request $request,
+        #[MapEntity(mapping: ['adminId' => 'id'])] ?Administrator $admin = null,
+        #[MapEntity(mapping: ['definitionId' => 'id'])] ?AdminAttributeDefinition $definition = null,
+    ): JsonResponse {
@@
-        if (!$definition || !$admin) {
+        if (!$definition || !$admin) {
             throw $this->createNotFoundException('Administrator attribute not found.');
         }
-        $attribute = $this->attributeManager->getAdminAttribute(
-            adminId: $admin->getId(),
-            attributeDefinitionId: $definition->getId()
-        );
-
-        return $this->json(
-            $this->normalizer->normalize($attribute),
-            Response::HTTP_OK
-        );
+        $attribute = $this->attributeManager->getAdminAttribute(
+            adminId: $admin->getId(),
+            attributeDefinitionId: $definition->getId()
+        );
+
+        if ($attribute === null) {
+            throw $this->createNotFoundException('Administrator attribute not found.');
+        }
+
+        return $this->json(
+            $this->normalizer->normalize($attribute),
+            Response::HTTP_OK
+        );

(Optional follow‑up: the method name getAttributeDefinition now effectively returns an attribute value, not the definition; renaming it in a future cleanup would make the intent clearer.)

🧹 Nitpick comments (6)
src/Messaging/Controller/CampaignController.php (3)

155-165: Null‑guard before auth in getMessage changes semantics; confirm this is desired

The explicit if ($message === null) { createNotFoundException(...) } is fine and keeps the controller from passing null into the service, but putting this check before requireAuthentication() means unauthenticated callers now see 404 vs 403 for non‑existent IDs. That’s a behavior change and also makes getMessage/updateMessage differ from sendMessage/deleteMessage in ordering.

If you want to avoid exposing resource existence to unauthenticated clients or keep all campaign endpoints consistent, consider either:

  • calling requireAuthentication() before the null‑check, or
  • updating the other endpoints (and their docs) to follow the same pattern.

Otherwise, the guard itself is fine.

Please double‑check with your API behavior/security expectations and adjust the ordering if needed.


294-309: Same null‑guard / auth‑ordering considerations in updateMessage

The null check with createNotFoundException('Campaign not found.') is correct and prevents passing null into the service, but—just like getMessage—it runs before $this->requireAuthentication($request). That means unauthenticated callers get 404 for unknown IDs instead of 403, and this differs from sendMessage/deleteMessage where auth is enforced first.

If that behavior change is intentional, you may want to:

  • align sendMessage (and its OA docs) to also surface 404, and/or
  • document this pattern as the standard for campaign routes.

If not intentional, move the null‑guard after requireAuthentication().

Please confirm the desired contract for 403 vs 404 across all campaign endpoints and adjust for consistency.


387-399: Consider documenting the 404 case for sendMessage as well

sendMessage already throws createNotFoundException('Campaign not found.') when $message === null, so at runtime clients can get a 404. The OA responses, however, only advertise 200 and 403.

For consistency with getMessage/updateMessage and to make client handling easier, consider adding a 404 NotFoundErrorResponse to this endpoint’s OpenAPI responses too.

After adding it, regenerate your OpenAPI spec to ensure the new 404 response is visible in the docs.

src/Identity/Controller/AdministratorController.php (1)

266-303: Delete endpoint rename is correct; tiny 204/JSON nit

The delete endpoint also uses adminId consistently across route, documentation, and MapEntity, so the refactor is solid. As a minor non‑blocking nit, if you ever touch this again you might consider returning an empty Response for 204 instead of json(null, 204) to align strictly with HTTP semantics.

src/Identity/Controller/AdminAttributeValueController.php (1)

135-205: Delete endpoint docs return 200, but implementation returns 204

The route/OA path changes for delete (/{adminId}/attributes/{definitionId} and corresponding OA path) are good and match the new tests. However, OA declares a 200 success response, while the controller returns Response::HTTP_NO_CONTENT (204) in Line 203. That mismatch may confuse API consumers and generated clients.

-            new OA\Response(
-                response: 200,
-                description: 'Success'
-            ),
+            new OA\Response(
+                response: 204,
+                description: 'Success (resource deleted, no content)'
+            ),
tests/Integration/Identity/Controller/AdminAttributeValueControllerTest.php (1)

29-183: Test URLs match the new /administrators/{adminId}/attributes API surface

All integration tests now hit /api/v2/administrators/{adminId}/attributes/{definitionId} (and /attributes for listing), which lines up with the controller’s new routing and OA paths. The scenarios for valid CRUD, invalid JSON, bad definitionId, and bad adminId look good.

If you want to exercise the new 404 behavior on the list endpoint specifically, you could add a small test that calls GET /api/v2/administrators/999999/attributes and asserts 404, mirroring the create‑with‑invalid‑adminId case.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 3f084aa and 1d54435.

📒 Files selected for processing (15)
  • src/Common/Validator/RequestValidator.php (0 hunks)
  • src/Identity/Controller/AdminAttributeValueController.php (6 hunks)
  • src/Identity/Controller/AdministratorController.php (7 hunks)
  • src/Identity/Request/UpdateAdministratorRequest.php (0 hunks)
  • src/Messaging/Controller/CampaignController.php (3 hunks)
  • src/Messaging/Controller/TemplateController.php (2 hunks)
  • src/Messaging/Request/CreateTemplateRequest.php (1 hunks)
  • src/Messaging/Request/UpdateMessageRequest.php (0 hunks)
  • src/Subscription/Controller/ListMembersController.php (2 hunks)
  • src/Subscription/Controller/SubscriberController.php (1 hunks)
  • src/Subscription/Request/UpdateSubscriberRequest.php (0 hunks)
  • tests/Integration/Identity/Controller/AdminAttributeValueControllerTest.php (9 hunks)
  • tests/Unit/Identity/Request/UpdateAdministratorRequestTest.php (0 hunks)
  • tests/Unit/Messaging/Request/UpdateMessageRequestTest.php (0 hunks)
  • tests/Unit/Subscription/Request/UpdateSubscriberRequestTest.php (0 hunks)
💤 Files with no reviewable changes (7)
  • src/Common/Validator/RequestValidator.php
  • src/Subscription/Request/UpdateSubscriberRequest.php
  • tests/Unit/Subscription/Request/UpdateSubscriberRequestTest.php
  • tests/Unit/Messaging/Request/UpdateMessageRequestTest.php
  • src/Messaging/Request/UpdateMessageRequest.php
  • src/Identity/Request/UpdateAdministratorRequest.php
  • tests/Unit/Identity/Request/UpdateAdministratorRequestTest.php
🧰 Additional context used
🧬 Code graph analysis (6)
src/Messaging/Request/CreateTemplateRequest.php (4)
src/Messaging/Request/Message/MessageMetadataRequest.php (1)
  • OA (12-33)
src/Messaging/Serializer/BounceRegexNormalizer.php (1)
  • OA (11-57)
src/Messaging/Serializer/MessageNormalizer.php (1)
  • OA (11-148)
src/Subscription/Serializer/SubscribePageNormalizer.php (1)
  • OA (12-52)
src/Subscription/Controller/SubscriberController.php (1)
src/Subscription/Request/UpdateSubscriberRequest.php (1)
  • getDto (49-59)
src/Messaging/Controller/TemplateController.php (1)
src/Messaging/Request/CreateTemplateRequest.php (1)
  • OA (14-78)
src/Identity/Controller/AdministratorController.php (3)
src/Subscription/Controller/SubscriberController.php (8)
  • Route (32-512)
  • Route (47-105)
  • Route (107-181)
  • Route (183-232)
  • Route (234-331)
  • Route (334-390)
  • Route (392-460)
  • Route (462-511)
src/Messaging/Controller/CampaignController.php (2)
  • Route (29-413)
  • Route (47-110)
src/Subscription/Controller/SubscriberAttributeDefinitionController.php (6)
  • Route (24-364)
  • Route (45-101)
  • Route (103-169)
  • Route (171-224)
  • Route (226-291)
  • Route (293-363)
src/Messaging/Controller/CampaignController.php (2)
src/Messaging/Serializer/MessageNormalizer.php (1)
  • OA (11-148)
src/Messaging/Service/CampaignService.php (1)
  • getMessage (38-45)
src/Identity/Controller/AdminAttributeValueController.php (3)
src/Subscription/Controller/SubscriberController.php (8)
  • Route (32-512)
  • Route (47-105)
  • Route (107-181)
  • Route (183-232)
  • Route (234-331)
  • Route (334-390)
  • Route (392-460)
  • Route (462-511)
src/Messaging/Controller/TemplateController.php (5)
  • Route (28-285)
  • Route (49-114)
  • Route (116-168)
  • Route (170-228)
  • Route (230-284)
src/Subscription/Controller/ListMembersController.php (3)
  • Route (22-187)
  • Route (39-123)
  • Route (125-186)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist latest [Build, Test]
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist oldest [Build, Test]
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist latest [Build, Test]
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist oldest [Build, Test]
🔇 Additional comments (10)
src/Subscription/Controller/SubscriberController.php (1)

172-176: Named arguments to updateSubscriber look correct and improve clarity

Using named parameters here lines up well with the updated SubscriberManager::updateSubscriber(subscriber, subscriberDto, admin) signature and makes the call site self-documenting. The wiring from MapEntity$subscribergetDto()updateSubscriber() is consistent, given that UpdateSubscriberRequest::getDto() now builds the DTO without an ID.

Only thing to keep an eye on: if the parameter names in SubscriberManager::updateSubscriber ever change, this call will need to be updated too, otherwise PHP will complain at runtime. Worth double-checking that the manager method currently uses exactly these parameter names.

src/Messaging/Controller/TemplateController.php (2)

108-110: LGTM! Nice readability improvement.

Switching to named arguments makes the call site more self-documenting. Clean refactor.


181-181: Good refactor – centralizes the schema definition.

Using a reference to CreateTemplateRequest keeps the schema in one place and makes it easier to maintain.

src/Messaging/Controller/CampaignController.php (2)

137-152: 404 response in OpenAPI for GET /campaigns/{messageId} looks good

The new 404 NotFoundErrorResponse in the docs matches the controller’s not‑found behavior and makes the API surface clearer for clients. 👍

Please regenerate your OpenAPI/Swagger spec and confirm the new 404 response appears as expected in the rendered docs.


271-292: 404 response in OpenAPI for PUT /campaigns/{messageId} is consistent and useful

Adding 404 NotFoundErrorResponse here aligns the docs with the new not‑found guard in updateMessage and with getMessage, which should help client implementations handle missing campaigns cleanly.

After updating, verify that your generated OpenAPI spec (and any client SDKs) pick up the new 404 response.

src/Identity/Controller/AdministratorController.php (2)

160-198: adminId rename is consistent across route, docs, and entity mapping

adminId is used consistently in the route placeholder, OA path, OA\Parameter, and MapEntity mapping, so this refactor should be transparent behavior‑wise and avoids the old administratorId/adminId mismatch.


209-252: Update endpoint param rename also looks clean

For the update route, adminId is wired through the Symfony route, OpenAPI path/parameter, and MapEntity mapping consistently, so the change keeps the behavior the same while standardizing the name.

src/Subscription/Controller/ListMembersController.php (1)

115-120: Named arguments for getPaginatedList look good

Using named args here (request, normalizer, className, filter) makes the call clearer and resilient to future parameter reordering in PaginatedDataProvider::getPaginatedList. No issues from my side.

src/Identity/Controller/AdminAttributeValueController.php (2)

25-55: Route nesting for admin attributes looks consistent

Using the controller prefix /administrators plus /{adminId}/attributes/{definitionId} and matching OA path /api/v2/administrators/{adminId}/attributes/{definitionId} keeps this in line with other controllers (e.g. templates/lists) and with the updated tests. No functional issues spotted here.


206-288: List endpoint refactor and named arguments look good

The move to /{adminId}/attributes plus OA path /api/v2/administrators/{adminId}/attributes aligns with the rest of the admin-attributes surface, and the added 404 response matches the if (!$admin) guard. Using named arguments for getPaginatedList with an AdminAttributeValueFilter keyed by adminId is clear and consistent with other controllers (e.g. list members/templates).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/Messaging/Request/CreateTemplateRequest.php (1)

65-76: Handle file_get_contents failure explicitly.

file_get_contents() returns string|false, but line 71 passes the result directly to the DTO which expects string|null. If the file read fails, false will be passed instead of null.

Apply this diff to handle the failure case:

         return new CreateTemplateDto(
             title: $this->title,
             content: $this->content,
             text: $this->text,
-            fileContent: $this->file instanceof UploadedFile ? file_get_contents($this->file->getPathname()) : null,
+            fileContent: $this->file instanceof UploadedFile 
+                ? (file_get_contents($this->file->getPathname()) ?: null) 
+                : null,
             shouldCheckLinks: $this->checkLinks,
             shouldCheckImages: $this->checkImages,
             shouldCheckExternalImages: $this->checkExternalImages,
         );
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1d54435 and ccfc48e.

📒 Files selected for processing (1)
  • src/Messaging/Request/CreateTemplateRequest.php (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
src/Messaging/Request/CreateTemplateRequest.php (2)
src/Messaging/Request/Message/MessageMetadataRequest.php (1)
  • OA (12-33)
src/Messaging/Serializer/BounceRegexNormalizer.php (1)
  • OA (11-57)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (5)
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist latest [Build, Test]
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist oldest [Build, Test]
  • GitHub Check: Checkout phpList rest-api and generate docs specification (OpenAPI latest-restapi.json)
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist oldest [Build, Test]
  • GitHub Check: phpList Base Dist on PHP 8.1, with dist latest [Build, Test]

Comment on lines 14 to 47
#[OA\Schema(
schema: 'CreateTemplateRequest',
required: ['title'],
properties: [
new OA\Property(property: 'title', type: 'string', example: 'Newsletter Template'),
new OA\Property(property: 'content', type: 'string', example: '<html><body>[CONTENT]</body></html>'),
new OA\Property(property: 'text', type: 'string', example: '[CONTENT]'),
new OA\Property(
property: 'file',
description: 'Optional file upload for HTML content',
type: 'string',
format: 'binary'
),
new OA\Property(
property: 'check_links',
description: 'Check that all links have full URLs',
type: 'boolean',
example: true
),
new OA\Property(
property: 'check_images',
description: 'Check that all images have full URLs',
type: 'boolean',
example: false
),
new OA\Property(
property: 'check_external_images',
description: 'Check that all external images exist',
type: 'boolean',
example: true
),
],
type: 'object'
)]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Clarify whether content is required or optional.

The content property (line 55) is declared as non-nullable string but isn't marked as required in the OpenAPI schema nor validated with NotBlank or NotNull. This creates ambiguity:

  • If content is required, add it to the required array and/or add validation constraints
  • If content is optional, declare it as ?string to match the OpenAPI schema

Apply this diff if content should be required:

 #[OA\Schema(
     schema: 'CreateTemplateRequest',
-    required: ['title'],
+    required: ['title', 'content'],
     properties: [

Or this diff if content should be optional:

-    #[ContainsPlaceholder]
-    public string $content;
+    #[ContainsPlaceholder]
+    public ?string $content = null;

And update line 69 in getDto() accordingly.

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/Messaging/Request/CreateTemplateRequest.php around lines 14-47, the OA
Schema declares content as a string but its required status is ambiguous; pick
one approach and apply it: if content should be required, add 'content' to the
schema's required array, add the appropriate Symfony validation annotation
(NotBlank or NotNull) to the content property, and ensure getDto() (line ~69)
returns a non-null string; if content should be optional, change the property
declaration to ?string, update any validation annotations to allow null, and
update getDto() (line ~69) to return ?string accordingly so the PHP type and
OpenAPI schema stay consistent.

@TatevikGr TatevikGr merged commit 0cebc96 into main Nov 21, 2025
9 checks passed
@TatevikGr TatevikGr deleted the refactor/admin-attributes-routes branch November 21, 2025 08:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants