Skip to content

refactor: extract HasResourceNavigation trait from BuildoraResource (refs #135)#173

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

refactor: extract HasResourceNavigation trait from BuildoraResource (refs #135)#173
ginkelsoft-development merged 1 commit into
developfrom
refactor/extract-resource-navigation-trait

Conversation

@ginkelsoft-development

Copy link
Copy Markdown
Owner

Tweede decomposition stap voor #135

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

Wijziging

src/Resources/Concerns/HasResourceNavigation.php (nieuw) bevat 4 methods:

Method Doel
title() Display label (default: model basename)
searchResultConfig() Global search label + columns
showInNavigation() Toon in admin nav (default: true)
slug() URL slug + permission prefix

BuildoraResource gebruikt nu use HasResourceNavigation;. Ongeveer 25 regels weg uit de god-class.

Behaviour is byte-identical:

  • title() blijft class_basename(\$this->modelClass)
  • searchResultConfig() blijft de Dutch UserBuildora-style defaults (bewust — niet een gedragsverandering nu)
  • showInNavigation() blijft true
  • slug() blijft str_replace('buildora', '', strtolower(class_basename(static::class)))

Tests — 7 tests, 17 asserties

Behavioural (5)

  • title() derives van model basename
  • showInNavigation() defaults true
  • ✓ Subclass kan opt out met return false
  • slug() strips 'buildora' correct (regression-belangrijk: routes en permissions hangen van dit format af)
  • searchResultConfig() shape preserved (label + columns keys)

Structural lock-in (2)

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

Voortgang #135

PR Concern Status
#172 HasResourceActions (6 methods) ✅ Open
deze HasResourceNavigation (4 methods) ✅ Open
Volgend HasResourceFields (5 methods) Te doen
Volgend HasResourceQuery (3 methods) Te doen

Na alle 4 PRs: BuildoraResource van 355 regels naar ~150, met elke concern in eigen trait + dedicated tests.

Refs #135

Second decomposition step for #135, following the HasResourceActions
trait. This one moves the four hooks that decide how a resource
identifies itself and surfaces in navigation/global search:

  - title()              — display label (defaults to model basename)
  - searchResultConfig() — global search label + columns
  - showInNavigation()   — whether to render in the admin nav
  - slug()               — URL slug and permission prefix

All four were stand-alone overridable hooks on BuildoraResource: a
consumer's CouponBuildora customises title() or searchResultConfig()
without touching the rest of the resource surface. Pulling them into
their own trait keeps that contract intact while taking ~25 lines out
of the resource class.

Behaviour is byte-identical:
  - title() still defaults to class_basename($this->modelClass)
  - searchResultConfig() returns the same default Dutch labels (kept
    on purpose — this is the package's built-in UserBuildora default,
    not a behaviour change to make here)
  - showInNavigation() still defaults to true
  - slug() still strips 'buildora' from the lowercased class basename

Tests (7) cover both behaviour and structure:
  - title() derives from the model basename
  - showInNavigation() defaults true; subclass can opt out to false
  - slug() strips 'buildora' and lowercases (regression: route prefix
    and permission strings depend on this exact format)
  - searchResultConfig() shape is preserved (label + columns keys)
  - BuildoraResource uses the trait (reflection)
  - Source grep on both files: methods present in the trait, absent
    from BuildoraResource.php (re-inlining fails this test)

Refs #135
@ginkelsoft-development
ginkelsoft-development force-pushed the refactor/extract-resource-navigation-trait branch from ff52f86 to 8f18627 Compare May 12, 2026 13:13
@ginkelsoft-development
ginkelsoft-development merged commit 34278f5 into develop May 12, 2026
11 of 12 checks passed
@ginkelsoft-development
ginkelsoft-development deleted the refactor/extract-resource-navigation-trait branch May 12, 2026 13:13
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