Sweep of CodeRabbit + arthurpar06 review items on PR #2215
(feat/route-bundles).
Bug fixes
- FlightsRelationManager: gate OldExport/OldImport actions on
!config('phpvms.use_queued_filament_imports') so they don't render
alongside the queued Filament Import/Export actions.
- FlightTimeBackfiller: move \$parsed++ into each per-field success
branch. Counters were row-vs-field unit mismatched, making the
completion log misleading (parsed=rows but failures=fields).
- FlightTimeBackfillerTest: replace Log::shouldReceive('warning')
->zeroOrMoreTimes() with ->once()->with(...) and Mockery::on(...)
payload matcher; the old expectation asserted nothing. Cast id to
int in the matcher (SQLite returns string IDs).
- FlightListShapeTest: assert both 'enabled' and 'active' keys in
the API contract structure (resource emits both as backward-compat
alias; previously only 'active' was locked in).
H1 — native AsEnumCollection for route_types
- Migration ..._add_capability_columns_to_subfleets_table.php: change
route_types from string(64) to json(). Portable across MySQL,
PostgreSQL and SQLite. Column is new in this PR so no data
migration needed.
- Subfleet model: cast switches from custom FlightTypesCast to
AsEnumCollection::of(FlightType::class).
- Delete app/Casts/FlightTypesCast.php and its unit test.
- Test updates explicitly document the behavior shift: empty selection
now stored as JSON [] rather than collapsed to null. Custom
behaviors lost: auto-dedupe, auto-sort, log+drop on invalid token.
None had consumers; future business logic can decide on the
null-vs-empty semantic.
H9 — split backfill into data migration
- Schema migration ..._add_time_columns_to_flights_table.php no
longer runs the backfill inline; just creates the columns.
- New database/migrations_data/2026_05_19_000000_backfill_flight_times.php
calls FlightTimeBackfiller::run() and is picked up by
MigrationService::runAllDataMigrations() on next admin update.
H2 — command rename to phpvms: prefix
- PreserveHiddenVisibility signature: flights:preserve-hidden-visibility
→ phpvms:preserve-hidden-visibility for consistency with the rest
of the namespace (phpvms:dev-install, :importer, :email-test,
:version).
- Updated refs in console test, docs/UPGRADING.md, and openspec
change-tracking docs (tasks, design, proposal).
H10 — composer scripts
- Add --parallel flag to 'pint' and 'pint:test' so AGENTS.md's
'composer pint --test' command uses multi-threading.
H5 — native badge for FlightForm status entry
- Refactor status_badge TextEntry from manual HtmlString + raw <span>
markup to TextEntry::badge()->color()->state(). Removes the need
for ->html(), manual e() escaping, and hardcoded Tailwind classes;
inherits Filament theming and dark-mode automatically.
R2-N — defense in depth
- Wrap :url substitution in e() in parentBundleOwnedDatesMessage().
FlightBundleResource::getUrl() is safe-by-construction but the
translation places :url in HTML context.
Collateral
- pint --dirty added an explicit ': array' return type to
FlightResource::toArray() (it had only @return array in PHPDoc).
BidFlightResource::toArray() needed the same change for covariance;
PHPStan would otherwise fail with method.childReturnType.
Prior session items (also included in this commit since not yet
committed):
- FlightTypesCast wrote validation + invalid-token logging.
- FlightsTable bundle-disabled badge with eager-loaded bundle.
- FlightImporter (Filament) added exists:flight_bundles,id rule.
- FlightImporter (Service) memoized default bundle id to avoid N+1.
- FlightForm: minDate as closure that skips for edit; fixed static
cache leak by using Laravel's container instead.
- SetVisibleFlights: DB::table → Flight::query() for ORM consistency.
- FlightBundle: #[Scope] attribute on visible scope; hasDates() as
has_dates Attribute accessor.
- FlightBundleTest, SubfleetCapabilityTest, FlightsBulkActionsTest
updated for new behaviors.
- ShieldSeeder dead-code cleanup.
All four pre-PR gates green: pint --test, phpstan, rector --dry-run,
pest on affected paths (180 tests passed).