SubscriptionRepository
\Benecaster\Membership\SubscriptionRepository
Data access for native membership subscription rows — the records behind Built-in Membership, including billing state, Stripe identifiers and the Promote to Bridge grace-period columns.
Every read path returns a row hydrated through the same whitelist, so a subscription array has the same shape and the same types wherever it came from. That matters most where a row is handed to third-party code: the benecaster_promote_grace_cleared and _extended actions pass one straight to listeners.
Methods
| Method | Visibility | Since | Description |
|---|---|---|---|
find_by_id( int $id ): ?array |
Public | — | Looks up one subscription row by primary key, hydrated through the same whitelist as every other read. Returns null for a non-positive id without querying, and null when no row matches. Exists so the grace-period actions can hand listeners a complete row rather than a narrow five-column shape. |
update_tier( int $subscription_id, string $new_tier_slug ): bool |
Public | — | Called from the admin and self-service tier-change paths, then NativeBridge::dispatch_change(), which fires benecaster_subscription_tier_changed. It also clears the subscription's price_id column — a tier change moves the subscriber off whichever cadence row they were matched to, so the stale price reference is dropped rather than left pointing at the old tier's price. |
find_price_change_candidates( int $show_id, string $tier_slug ): array |
Public | — | Returns every Stripe-billed subscription on the tier that is still live (active, trialing or past due) and not cancelling at period end. Paused subscriptions are included; comped ones are not. This is the raw pool a scheduled price change narrows to one cadence and then through the benecaster_price_change_cohort filter. It is also one half of the "still paying" test that stops a tier being made free; the other half is anyone with a plan change scheduled onto the tier. |
find_billing_for_show( int $show_id ): array |
Public | — | Returns the active-or-past_due benecaster_subscriptions rows for a Built-in Membership show, each joined to its benecaster_membership_prices row via price_id (falling back to a billing-interval match on older rows with no price_id). This is the candidate pool Membership\NativeRevenueEstimator sums into the dashboard's revenue_estimate — trials, paused subscriptions, subscriptions set to cancel, and manually-comped subscribers are excluded before this method returns, not filtered afterward by the caller. |
set_pending_switch( int $id, int $price_id, string $stripe_price_id, string $switch_at_utc, string $schedule_id ): bool |
Public | — | Writes the pending-switch columns (pending_price_id, pending_stripe_price_id, pending_switch_at, stripe_schedule_id) once Benecaster has built the Stripe Subscription Schedule for a subscriber's plan change. |
clear_pending_switch( int $id ): bool |
Public | — | Nulls the pending-switch columns without changing price_id or billing_interval — used when a pending switch is cancelled or dropped, not when it completes. |
complete_switch( int $id, int $price_id, string $billing_interval, ?string $tier_slug = null ): bool |
Public | — | Writes the new price_id and billing_interval and clears the pending-switch columns in one update, once Benecaster sees the Stripe Subscription Schedule's phase change land. Pass $tier_slug for a tier move; null means a billing-period switch and leaves the tier column untouched. |
land_on_free_tier( int $id, string $tier_slug ): bool |
Public | — | Converts the row into a free membership on $tier_slug when a scheduled move onto the free tier lands: billing_interval 'free', status active, no price, nothing pending. The Stripe subscription id is kept, so every listener on the deletion event can still find the row. |
detach_stripe_subscription( int $id ): bool |
Public | — | Clears the row's Stripe subscription id. Called at the end of the deletion cascade for a landed free move, never during it, so the row does not keep claiming a subscription that no longer exists. |
Notes
Only the members relevant to published extension points are documented here. The class carries other internal read and write paths that are not developer surface and may change without notice.