Skip to content

replace controller logic with dedicated handler and service classes (CQRS-Lite)#91

Draft
solverat wants to merge 10 commits into
1.xfrom
controller-to-services
Draft

replace controller logic with dedicated handler and service classes (CQRS-Lite)#91
solverat wants to merge 10 commits into
1.xfrom
controller-to-services

Conversation

@solverat

Copy link
Copy Markdown
Contributor

Extracts all business logic from admin controllers into dedicated handler, service, and enricher classes. Controllers are now thin dispatch layers: they receive a typed Payload, pass it to a Handler, and return the result. Request parsing no longer happens inside controllers or handlers.

Changes 🤯

Handlers & Payloads

Every controller action now has a corresponding Handler (invokable) and a Payload implementing ExtJsPayloadInterface. The payload is resolved from the request by a new ExtJsValueResolver, keeping Request out of handlers entirely.

Common payload shapes (IdQueryPayload, IdBodyPayload, EmptyPayload, etc.) live in src/Payload/Common/.

Services

Business logic shared across handlers was extracted into service classes under src/Service/:

  • Document/DocumentPayloadMapper, DocumentPersistenceCoordinator
  • Asset/AssetPayloadMapper
  • DataObject/DataObjectPayloadMapper
  • Grid/GridColumnConfigService, GridBatchService, GridExportService
  • Element/EditLockService, Element/SessionService
  • Login/LoginPageService
  • Workflow/WorkflowElementResolver
  • Translation/AdminSearchTermResolver

Enrichers

Post-processing of element data was split into enrichers under src/Enricher/:

  • Element/AdminStyleEnricher, Element/UserNamesEnricher
  • Document/DocumentMetaEnricher, DraftEnricher, PropertiesEnricher, TranslationEnricher
  • DataObject/DraftEnricher, CustomLayoutEnricher

Permissions

Access control moved from manual checkPermission() calls inside controller methods to #[IsGranted] attributes on actions, backed by PermissionVoter.

HTTP layer

  • ExtJsValueResolver resolves Payload objects from the request via fromRequest()
  • ApiResponse DTO for consistent JSON response shape

ExtJS xaction dispatching

ExtJS CRUD endpoints that send a single URL with an xaction parameter (create, update, destroy) are now handled via $this->forward() to dedicated per-action methods. Each target action has its own typed Payload, Handler, and #[IsGranted] attribute instead of a branching switch statement inside one fat action.

Removed

  • src/Controller/Traits/ApplySchedulerDataTrait, UserNameTrait
  • src/EventListener/Traits/ControllerTypeTrait

@solverat solverat requested a review from benwalch June 18, 2026 14:44
@solverat solverat added the enhancement New feature or request label Jun 18, 2026
@solverat solverat changed the title replace controller logic with dedicated handler and service classes (CQRS-Lite)Controller to services replace controller logic with dedicated handler and service classes (CQRS-Lite) Jun 18, 2026
@solverat solverat removed the request for review from benwalch June 18, 2026 14:45
@solverat solverat self-assigned this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant