Skip to content

v2.2.0 — derived resync + OneSignalObserver

Latest

Choose a tag to compare

@rodrigocoliveira rodrigocoliveira released this 30 Jul 02:44
cb69db7

Owns the full OneSignal lifecycle with far less app-side code: add one attribute to your model and the package keeps OneSignal in step with it.

Automatic sync via #[ObservedBy]

#[ObservedBy(OneSignalObserver::class)]
class User extends Authenticatable
{
    use HasOneSignal;
}

No field list, no wasChanged() guard, no enablement check, no queue lookup. On every save the observer asks oneSignalPayloadChanged(), which builds the payload from the model's current attributes and from its original attributes and compares — so a tag added to getOneSignalTags() is covered the day it lands. Handles create, update, delete (leaving soft-deleted profiles intact until forceDelete()) and restore.

The README documents the boundary rather than implying full coverage: a related row's content changing, and many-to-many attach/detach, fire no event on the user, so those need an observer on the related model plus scheduled onesignal:backfill as reconciliation.

Async delete

deleteFromOneSignalAsync() and Jobs\DeleteUserFromOneSignal complete the delete path with the same retry policy as sync — a transient 5xx no longer permanently orphans a profile. A 404 is treated as a completed erasure: logged at debug, not retried.

Lazy manager reads

OneSignalManager reads enabled, app_id and track_events from config() at call time instead of snapshotting them, and builds the SDK client on first use, so a disabled package never constructs a Guzzle client. Tests no longer need app()->forgetInstance(OneSignalManager::class) to observe a config change.

Before you upgrade

Three compatibility notes in UPGRADE.md: the removed protected validatedOneSignalPhone() helper (an override of it now silently stops running), both jobs becoming afterCommit, and direct OneSignalManager construction following config when no explicit enabled: argument is passed.

Full notes in CHANGELOG.md.