Releases: cjmellor/engageify
Release list
v2.1.1
A patch release fixing two correctness bugs in HasEngagements. No API or migration changes.
Fixed
Disengagedis no longer dispatched when nothing was removed.disengage()guarded the delete and the counter adjustment behind a non-empty check but fired the event unconditionally, so disengaging something that was never engaged emitted a phantom event. This brings it in line withflipExclusive(), which only ever emitted the event for rows it actually deleted. Listeners can now treat everyDisengagedas a real deletion.- Closed a check-then-insert race in
engage(). Withallow_multiple_engagements = falsethe duplicate guard ran outside the transaction, so concurrent requests could both pass it, both insert, and double-count the counter. The check now runs inside the transaction underlockForUpdate(), matchingrate()andflipExclusive(). Note that gap-locking prevents the phantom insert on MySQL and SQLite serialises writes, but PostgreSQL does not gap-lock aSELECT ... FOR UPDATEmatching zero rows.
Full Changelog: v2.1.0...v2.1.1
v2.1.0
Engaging as a specific actor
Engagements previously resolved the acting user from auth() alone, so applications whose authenticated principal is not the model that owns engagements — multi-tenant setups, impersonation, queued jobs, seeders — could not use the trait's mutators at all.
engage(), disengage() and the convenience verbs (like, dislike, upvote, downvote, unlike, toggleLike) now take an optional trailing actor, defaulting to the authenticated user as before:
$post->engage(Reaction::Bookmark, actor: $user);
$post->like(actor: $user);
$post->unlike(actor: $user);The resolved actor is what gets written to user_id, what scopes the duplicate-engagement guard, the exclusive-group flip and the rating upsert, and what the Engaged/Disengaged events carry.
Fixed
Exclusive-group flips dispatched events reporting auth()->user() while deleting rows keyed on auth()->id(). Those are now consistently the same actor — a correctness fix that applies even when no explicit actor is passed.
Engaging with no actor and nobody authenticated now throws UserCannotEngageException with a clear message, rather than failing deeper in the stack.
Upgrading
Nothing to do. The actor parameter is a new optional trailing argument throughout, so this is a drop-in upgrade from v2.0.0 with no migration and no config change.
withUserEngagement() keeps its existing $user parameter name rather than being renamed to $actor, so named-argument callers are unaffected. It takes the same model you would pass as actor:.
Maintenance
The development dependency lock was refreshed onto current releases, clearing the open Dependabot alerts against composer.lock. These were all development-only transitive dependencies pulled in through orchestra/testbench — the package requires only illuminate/database and illuminate/support, and consumers resolve their own dependencies, so no installation of engageify was affected.
Full Changelog: v2.0.0...v2.1.0
v2.0.0
A major release adding ratings, view & impression tracking, Hot/Top ranking, weighted and custom engagement Verbs, and actor-side queries.
⚠️ Breaking changes — read the upgrade guide before upgrading from v1. In short: raised to PHP 8.3 / Laravel 12+, theEngageifyfacade is removed, and the five reaction-specific events are replaced by genericEngaged/Disengaged. Existing installs must runphp artisan engageify:recountonce after migrating.
Added
- Custom & multiple Verb enums — implement
EngagementType;engageify.typesaccepts a single enum or an array. - Weighted Verbs & engagement values (
valuecolumn,HasWeight). - Exclusive groups (vote-style).
- Ratings on a configurable scale (
Rateable) with Bayesian-average ranking. - Hot / Top ranking backed by a denormalised
engagement_counterstable. - Actor-side queries (
EngagesWith,withUserEngagement()). - View tracking (
HasViews) + opt-in time-windowed views. - Impression tracking — signed-token viewport endpoint,
@impressionBlade directive, optional injectable browser tracker. engageify:recountcommand.- Generic
Engaged/Disengagedevents.
Changed
- Counts and scores now read from a denormalised
engagement_counterstable (runengageify:recountonce when upgrading). - Minimum requirements raised to PHP
^8.3and Laravel^12.0|^13.0.
Removed
- The
Engageifyfacade and itsEngageifyalias. - The five reaction-specific events (use
Engaged/Disengaged). - The in-memory cache layer (
allow_caching/cache_duration).
Full upgrade guide: https://github.com/cjmellor/engageify/blob/2.x/UPGRADING.md
v1.0.1
What's Changed
- build(deps): Bump dependabot/fetch-metadata from 1.6.0 to 2.0.0 by @dependabot[bot] in #5
- build(deps): Bump aglipanci/laravel-pint-action from 2.3.1 to 2.4 by @dependabot[bot] in #6
- build(deps): Bump dependabot/fetch-metadata from 2.0.0 to 2.1.0 by @dependabot[bot] in #7
- build(deps): Bump dependabot/fetch-metadata from 2.1.0 to 2.2.0 by @dependabot[bot] in #8
- build(deps): Bump dependabot/fetch-metadata from 2.2.0 to 2.3.0 by @dependabot[bot] in #9
- build(deps): Bump aglipanci/laravel-pint-action from 2.4 to 2.5 by @dependabot[bot] in #10
- build(deps): Bump dependabot/fetch-metadata from 2.3.0 to 2.4.0 by @dependabot[bot] in #11
- build(deps): Bump stefanzweifel/git-auto-commit-action from 5 to 6 by @dependabot[bot] in #12
Full Changelog: v1.0.0...v1.0.1
v1.0.0
What's Changed
- build(deps): Bump stefanzweifel/git-auto-commit-action from 4 to 5 by @dependabot in #2
- build(deps): Bump aglipanci/laravel-pint-action from 2.3.0 to 2.3.1 by @dependabot in #3
- Laravel 11 Compatibility by @cjmellor in #4
New Contributors
Full Changelog: v0.0.1...v1.0.0