whisper-money/app/Http/Middleware
Víctor Falcón 6b441a0f02
refactor(inertia): group the shared user props and name the inline conditions (#773)
## Why

`HandleInertiaRequests::share` was at cyclomatic complexity **18** — the
highest left after #771. Almost all of it was one shape repeated seven
times:

```php
'bankingConnections' => fn () => $user ? $user->bankingConnections()->get(...)->map(...) : [],
'accounts'           => fn () => $user ? $user->accounts()->...->get() : [],
'categories'         => fn () => $user ? $user->categories()->forDisplay()->get() : [],
// ...four more
```

Each of those ternaries is a branch, and the guest answer is the same
every time.

## What changed

**`userCollectionProps()`** owns the seven deferred props. The guest
case is answered once, up front:

```php
if ($user === null) {
    return array_fill_keys(['expiredBankingConnections', 'bankingConnections', /* ... */], fn () => []);
}
```

…so the seven queries below read as queries rather than as ternaries.
`automationRules` was the odd one out (a full closure with an early
`return []`) and now matches its siblings.

**Three conditions got names** instead of living inline in the props
array:

| method | was |
|---|---|
| `isDemoAccount()` | `$user?->isDemoAccount() && !
app()->environment('local')` |
| `demoCredentials()` | `config(...) && ($isDemoQuery \|\|
$isDemoAccount) ? [...] : null` |
| `hasResidualEncryptionArtifacts()` | the four-way `&&` chain gating
the cleanup job |

The comments now say *why* each one is what it is — that a demo account
is only treated as one outside local, and that the cleanup job fires
when the salt outlived the encrypted rows.

## Behaviour

One deliberate change: `expiredBankingConnections` and
`bankingConnections` end in `->all()`, returning a plain list instead of
a `Collection`. The JSON is identical (a Collection of arrays serializes
to the same array), and it keeps the prop's type expressible outside
`share()` — `Collection`'s `TValue` is invariant, so phpstan cannot
match `Closure(): Collection<int, array{…}>` against itself once the
array literal lives in its own method.

Everything else is a move.

## Metrics

| | before | after |
|---|---|---|
| `share` | 18 | 4 |
| `userCollectionProps` (new) | — | 2 |
| `demoCredentials` / `hasResidualEncryptionArtifacts` / `isDemoAccount`
(new) | — | 3 / 4 / 2 |

## Testing

This middleware runs on every page, so: **the whole Feature suite — 1958
tests, 1957 passed, 1 skipped.** PHPStan clean.

`InertiaSharedDataTest` covers exactly what moved: the guest path, the
authenticated path, both encryption-cleanup branches (queued when the
salt is residual, not queued when there is no salt), the
expired-connection reconnect links and the connections prop — the two
props whose return type changed.
2026-08-11 13:09:55 +00:00
..
BlockDemoAccountActions.php feat: Spanish localization (#74) 2026-02-08 11:58:08 +01:00
EnsureOnboardingComplete.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00
EnsureUserIsSubscribed.php feat(paywall): require a plan when the user has accepted AI (#564) 2026-06-19 14:18:49 +00:00
HandleAppearance.php chore: upgrade Laravel 12 to 13 (#242) 2026-03-25 12:56:33 +00:00
HandleInertiaRequests.php refactor(inertia): group the shared user props and name the inline conditions (#773) 2026-08-11 13:09:55 +00:00
SetLocale.php refactor: centralize duplicated provider & locale keys into enums (#543) 2026-06-16 13:43:14 +00:00
SetSentryUser.php Add Sentry user context (#348) 2026-05-04 13:26:50 +01:00
TrackLastActiveAt.php feat(users): track last login and last active timestamps (#516) 2026-06-10 11:01:30 +02:00
WithoutSsr.php Disable SSR for dashboard routes and extract API routes (#19) 2025-12-08 19:21:48 +01:00