EEPIC-#79 - v3 refactor: PSR-compliant client with typed DTOs, reposi…#153
Open
derpixler wants to merge 1 commit into
Open
EEPIC-#79 - v3 refactor: PSR-compliant client with typed DTOs, reposi…#153derpixler wants to merge 1 commit into
derpixler wants to merge 1 commit into
Conversation
derpixler
force-pushed
the
epic-79/pre-merge-develop
branch
8 times, most recently
from
July 18, 2026 02:44
ee24898 to
44542a8
Compare
…tories, enums, PHP 8.1+ ## Breaking Changes (v2 → v3) ### Architecture - ZammadClient with typed factory methods replaces Client (arrays, magic strings) - Repository pattern + typed DTOs replaces Resource + ResourceType enums - Typed exceptions (NotFoundException, etc.) replaces hasError()/getError() - PHP >= 8.1 (was PHP >= 7.2) ### Files removed (~3,900 LOC) - src/Client.php, src/HTTPClient.php, src/HTTPClientInterface.php - src/Resource/ — all 10 resource classes - src/ResourceType.php, src/Exception/ - test/ZammadAPIClient/ — old test suite - examples/ticket.php, examples/user.php, examples/v2-usage.php ## What's new (~10,200 LOC) ### Core (src/Core/) - ZammadClient, RequestHandler, RetryAfterMiddleware, AbstractRepository, PaginatedList, Resource, DtoHydrator, Cast, ConnectionConfig, RepositoryRegistry, ResponseParser, HttpPageFetcher, traits ### Contracts (src/Core/Contracts/) - RepositoryInterface, DTOInterface, DeletableInterface, PatchableInterface, RequestHandlerInterface, ClientInterface, PageFetcherInterface ### Endpoints — 10 repositories + typed DTOs (src/Endpoints/) - Tickets (CRUD + delete + getTicketArticles), TicketDTO, TicketUpdateDTO - Users (CRUD + delete + CSV import), UserDTO - Organizations (CRUD + delete + CSV import), OrganizationDTO - Groups (CRUD + delete), GroupDTO - TicketArticles (getForTicket, getAttachmentContent), TicketArticleDTO, TicketArticleType enum (Note, Email, Phone, Sms, Web) - TicketStates (read-only), TicketStateDTO - TicketPriorities (read-only), TicketPriorityDTO - Tags (add, remove, tagSearch), TagDTO - TextModules (CRUD + delete + CSV import), TextModuleDTO - Links (add, remove, list), LinkDTO ### Exceptions — typed hierarchy (src/Exceptions/) - AuthenticationException (401), ForbiddenException (403), NotFoundException (404), ValidationException (422, with $errors array), RateLimitException (429, auto-retried), ServerErrorException (5xx), NetworkException ### Bridge (src/Bridge/) - LaravelServiceProvider, SymfonyBundle ### Tests — 227 unit tests, 12 integration test classes ### Documentation - docs/migration-v3.md, docs/migration-v3-examples.md (15 side-by-side examples) - docs/v2-reference.md, docs/alternative-clients.md - examples/cookbook.php (9 runnable v3 recipes) - README.md with DTO field tables, update decision guide, error mapping, paradigm guide, delete() availability table
derpixler
force-pushed
the
epic-79/pre-merge-develop
branch
from
July 19, 2026 05:52
44542a8 to
ac65aee
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
EEPIC-#79 — v3: PSR-compliant PHP client with typed DTOs, repositories, and enums
Breaking Changes (v2 → v3)
Architecture
Client(arrays, magic strings)ZammadClientwith typed factory methodsResource+ResourceTypeenums$ticket->getValue('title')$ticket->title(typed property, IDE autocomplete)$ticket->hasError()/$ticket->getError()new Client(['url' => ..., 'http_token' => ...])ZammadClient::withToken($url, $token)Files removed (~3,900 LOC)
src/Client.php,src/HTTPClient.php,src/HTTPClientInterface.phpsrc/Resource/— all 10 resource classes (AbstractResource, Ticket, User, etc.)src/ResourceType.phpsrc/Exception/— old exception classestest/ZammadAPIClient/— old test suiteWhat's new (~10,200 LOC)
Core layer (
src/Core/)ZammadClient— entry point withwithToken(),withOAuth2(),withBasicAuth(),withClient(). Auto-normalizes URL (appends/api/v1). Memoized repositories viarepo().Impersonation via
performOnBehalfOf()/setOnBehalfOfUser().RequestHandler— PSR-18 HTTP transport with JSON (de)serialization, HTTP status→exceptionmapping, X-On-Behalf-Of header support, configurable retries.
RetryAfterMiddleware— PSR-18 decorator: auto-retries on HTTP 429 with Respect-Retry-Afterheader parsing (RFC 7231 HTTP-date + delta-seconds).
AbstractRepository— generic CRUD with generator-based cursor pagination, explicit pagemethods,
resource()/list()Ruby-style accessors,extractItems().PaginatedList— ArrayAccess + IteratorAggregate withpage(),pageNext(),pagePrev(),each(),totalCount(),allPages().Resource— mutable stateful wrapper with property-level change tracking.save()sends only changed fields;destroy()sends DELETE.DtoHydrator— reflection-based hydration: maps API array keys to constructor parameterswith type-driven coercion via
Cast.Cast— safe scalar coercions:dateTime(),string(),intOrNull(),boolOrNull().ConnectionConfig— immutable config DTO (verifySsl, timeout, maxRetries, logger).RepositoryRegistry— single source of truth mapping 10 repositories to API paths and DTOs.ResponseParser— extracts resource arrays from Zammad's{tickets: [...], assets: {...}}wrapper.HttpPageFetcher— PSR-18 page fetcher for PaginatedList.HasTimestamps,HydratesFromArray,SerializesToArray.Contracts (
src/Core/Contracts/)RepositoryInterface— find, all, search, create, update, patch, deleteDTOInterface— fromArray(), toArray(), id()DeletableInterface— delete($id)PatchableInterface— toPatchArray()RequestHandlerInterface,ClientInterface,PageFetcherInterfaceEndpoints — 10 repositories + typed DTOs (
src/Endpoints/)TicketRepository(CRUD + delete + getTicketArticles),TicketDTO(14 fields),TicketUpdateDTO(partial update, 8 fields)UserRepository(CRUD + delete + CSV import),UserDTO(13 fields)OrganizationRepository(CRUD + delete + CSV import),OrganizationDTOGroupRepository(CRUD + delete),GroupDTOTicketArticleRepository(getForTicket, getAttachmentContent),TicketArticleDTO(25 fields),TicketArticleTypeenum (Note, Email, Phone, Sms, Web)TicketStateRepository,TicketStateDTOTicketPriorityRepository,TicketPriorityDTOTagRepository(add, remove, tagSearch),TagDTOTextModuleRepository(CRUD + delete + CSV import),TextModuleDTOLinkRepository(add, remove, list),LinkDTOExceptions (
src/Exceptions/) — typed hierarchyAuthenticationException(401),ForbiddenException(403),NotFoundException(404)ValidationException(422, with$errorsarray per-field)RateLimitException(429, with$retryAfterSeconds, auto-retried)ServerErrorException(5xx),NetworkException(DNS, timeout, connection refused)Bridge (
src/Bridge/)LaravelServiceProvider— auto-registers ZammadClient as singletonSymfonyBundle— Symfony DI integrationTests — 227 unit tests, 12 integration test classes
RepositoryRegistry, RetryAfterMiddleware, all DTOs, all repositories, ZammadClient
Pagination, Search, ErrorHandling, ReferenceData, User cleanup
Documentation
docs/migration-v3.md— step-by-step v2→v3 migration guidedocs/migration-v3-examples.md— 15 side-by-side before/after code examplesdocs/v2-reference.md— preserved v2 documentationdocs/alternative-clients.md— non-Guzzle transport setupexamples/cookbook.php— 9 runnable v3 recipesREADME.md— rewritten with DTO field tables, update method decision guide,error handling table (HTTP→exception mapping + auto-retry), paradigm guide
CI
integration tests against live Zammad instance