Skip to content

refactor: extract HasResourceQuery trait from BuildoraResource (refs #135)#174

Merged
ginkelsoft-development merged 1 commit into
developfrom
refactor/extract-resource-query-trait
May 12, 2026
Merged

refactor: extract HasResourceQuery trait from BuildoraResource (refs #135)#174
ginkelsoft-development merged 1 commit into
developfrom
refactor/extract-resource-query-trait

Conversation

@ginkelsoft-development

Copy link
Copy Markdown
Owner

Derde decomposition stap voor #135

Volgt op PR #172 (HasResourceActions) en PR #173 (HasResourceNavigation). Zelfde patroon: één concern per PR, behoud subclass-override contract via traits.

Wijziging

src/Resources/Concerns/HasResourceQuery.php (nieuw) bevat de 2 static query entry points:

Method Doel
query() List-context query (geen panel eager-loads)
queryWithRelations() Detail-context query (wel)

BuildoraResource gebruikt nu use HasResourceQuery;. Geen behaviour change — beide methodes forwarden onveranderd naar QueryFactory::make().

Composeert cleanly met andere PRs

Tests — 5 tests, 8 asserties

Behavioural (3)

  • query() returnt een BuildoraQueryBuilder
  • query() stages geen panel eager-loads (list-context invariant)
  • queryWithRelations() stages declared panel relations (detail-context invariant)

Structural (2)

  • BuildoraResource uses de trait
  • ✓ Source-grep: methods absent uit BuildoraResource.php, present in trait file

Voortgang #135

PR Concern Status
#172 HasResourceActions (6 methods) ✅ Open
#173 HasResourceNavigation (4 methods) ✅ Open
deze HasResourceQuery (2 methods) ✅ Open
Volgend HasResourceFields (5 methods — fill/getFields/setFields/resolveFields/defineFields abstract) Te doen

Na deze 4 PRs is BuildoraResource gestript tot ongeveer 150 regels — alleen nog de constructor, parentModel/fields/detailView state, getRelationResources/getModelInstance/getModelClass/setDetailView/getDetailView, en de abstract defineFields(). Een veel cleaner basis voor toekomstige uitbreidingen.

Refs #135

Third decomposition step for #135 (after HasResourceActions and
HasResourceNavigation). Moves the two static query entry points out
of BuildoraResource into Resources\Concerns\HasResourceQuery:

  - query()              — list-context query (no panel eager-loads)
  - queryWithRelations() — detail-context query (eager-loads panels)

Both are thin forwards to QueryFactory; they could in principle stay
on the resource class, but keeping them with the other resource
concerns being extracted gives BuildoraResource a single ownership
story: 'every overridable hook lives in a trait'.

The list/detail split itself (the boolean second argument to
QueryFactory::make()) is unchanged here — that's the subject of #129 /
PR #166, which makes the entry points explicit (forList/forDetail).
The two efforts compose cleanly: after both land, this trait calls
QueryFactory::forList() and forDetail() instead of make($resource, bool).

Tests (5):
  - query() returns a BuildoraQueryBuilder
  - query() does not stage panel eager-loads (list-context invariant)
  - queryWithRelations() stages declared panel relations (detail-context
    invariant)
  - BuildoraResource uses the trait (reflection)
  - Source grep: methods absent from BuildoraResource.php, present in
    HasResourceQuery.php — re-inlining fails the test.

Refs #135
@ginkelsoft-development
ginkelsoft-development force-pushed the refactor/extract-resource-query-trait branch from 017657f to e8ff3c0 Compare May 12, 2026 13:14
@ginkelsoft-development
ginkelsoft-development merged commit 09039ad into develop May 12, 2026
11 of 12 checks passed
@ginkelsoft-development
ginkelsoft-development deleted the refactor/extract-resource-query-trait branch May 12, 2026 13:14
ginkelsoft-development added a commit that referenced this pull request May 12, 2026
Fourth and final decomposition step for #135. After this, every
overridable resource hook lives in a dedicated trait under
Resources\Concerns and the BuildoraResource class itself shrinks from
~355 lines to ~150 — covering only constructor, state declarations,
model resolution, panel relations, detail-view configuration and the
abstract defineFields() contract.

This PR moves four methods covering field state management into
Resources\Concerns\HasResourceFields:

  - fill(Model)           — populate every field's value/displayValue
                            from a model
  - setFields(array)      — replace the field collection with
                            type validation
  - getFields()           — read the field collection with the same
                            defensive Field-type check
  - resolveFields($model) — re-prepare the fields for a specific model
                            via FieldManager::prepare

The abstract defineFields(): array contract stays on BuildoraResource.
Abstract hooks declared via a trait are harder to discover (PHPStorm
doesn't surface them as 'implement me' candidates when you extend the
class), and the subclass-implementation contract is the resource's
defining feature — it belongs on the resource itself.

State access: the trait reads/writes $this->fields and
$this->parentModel, both protected properties declared on
BuildoraResource. PHP allows that without re-declaration in the trait.

Tests (7):
  - getFields() returns the declared fields
  - fill() sets the value on the field from the model attribute
  - setFields() throws BuildoraException on non-Field entries
  - setFields() accepts a valid Field[] array
  - resolveFields($model) re-prepares fields for that model
  - BuildoraResource uses the trait (reflection)
  - Source-grep both files: methods present in the trait, absent from
    BuildoraResource.php. defineFields stays on the resource (abstract).

After #172, #173, #174 and this PR are merged, #135 is closed.

Refs #135
ginkelsoft-development added a commit that referenced this pull request May 12, 2026
Fourth and final decomposition step for #135. After this, every
overridable resource hook lives in a dedicated trait under
Resources\Concerns and the BuildoraResource class itself shrinks from
~355 lines to ~150 — covering only constructor, state declarations,
model resolution, panel relations, detail-view configuration and the
abstract defineFields() contract.

This PR moves four methods covering field state management into
Resources\Concerns\HasResourceFields:

  - fill(Model)           — populate every field's value/displayValue
                            from a model
  - setFields(array)      — replace the field collection with
                            type validation
  - getFields()           — read the field collection with the same
                            defensive Field-type check
  - resolveFields($model) — re-prepare the fields for a specific model
                            via FieldManager::prepare

The abstract defineFields(): array contract stays on BuildoraResource.
Abstract hooks declared via a trait are harder to discover (PHPStorm
doesn't surface them as 'implement me' candidates when you extend the
class), and the subclass-implementation contract is the resource's
defining feature — it belongs on the resource itself.

State access: the trait reads/writes $this->fields and
$this->parentModel, both protected properties declared on
BuildoraResource. PHP allows that without re-declaration in the trait.

Tests (7):
  - getFields() returns the declared fields
  - fill() sets the value on the field from the model attribute
  - setFields() throws BuildoraException on non-Field entries
  - setFields() accepts a valid Field[] array
  - resolveFields($model) re-prepares fields for that model
  - BuildoraResource uses the trait (reflection)
  - Source-grep both files: methods present in the trait, absent from
    BuildoraResource.php. defineFields stays on the resource (abstract).

After #172, #173, #174 and this PR are merged, #135 is closed.

Refs #135
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.

1 participant