guard($actor, $collection); $inserted = false; DB::transaction(function () use ($actor, $collection, $context, $contextMeta, &$inserted): void { $rows = DB::table('collection_saves')->insertOrIgnore([ 'collection_id' => $collection->id, 'user_id' => $actor->id, 'created_at' => now(), 'last_viewed_at' => now(), 'save_context' => $context, 'save_context_meta_json' => $contextMeta === [] ? null : json_encode($contextMeta, JSON_THROW_ON_ERROR), ]); if ($rows === 0) { DB::table('collection_saves') ->where('collection_id', $collection->id) ->where('user_id', $actor->id) ->update([ 'last_viewed_at' => now(), 'save_context' => $context, 'save_context_meta_json' => $contextMeta === [] ? null : json_encode($contextMeta, JSON_THROW_ON_ERROR), ]); return; } $inserted = true; DB::table('collections') ->where('id', $collection->id) ->update([ 'saves_count' => DB::raw('saves_count + 1'), 'last_activity_at' => now(), 'updated_at' => now(), ]); }); return $inserted; } public function touchSavedCollectionView(?User $actor, Collection $collection): void { if (! $actor) { return; } DB::table('collection_saves') ->where('collection_id', $collection->id) ->where('user_id', $actor->id) ->update([ 'last_viewed_at' => now(), ]); } public function unsave(User $actor, Collection $collection): bool { $deleted = false; DB::transaction(function () use ($actor, $collection, &$deleted): void { $rows = DB::table('collection_saves') ->where('collection_id', $collection->id) ->where('user_id', $actor->id) ->delete(); if ($rows === 0) { return; } $deleted = true; $savedListIds = DB::table('collection_saved_lists') ->where('user_id', $actor->id) ->pluck('id'); if ($savedListIds->isNotEmpty()) { DB::table('collection_saved_list_items') ->whereIn('saved_list_id', $savedListIds->all()) ->where('collection_id', $collection->id) ->delete(); } DB::table('collections') ->where('id', $collection->id) ->where('saves_count', '>', 0) ->update([ 'saves_count' => DB::raw('saves_count - 1'), 'updated_at' => now(), ]); }); return $deleted; } public function isSaved(?User $viewer, Collection $collection): bool { if (! $viewer) { return false; } return DB::table('collection_saves') ->where('collection_id', $collection->id) ->where('user_id', $viewer->id) ->exists(); } private function guard(User $actor, Collection $collection): void { if (! $collection->canBeSavedBy($actor)) { throw ValidationException::withMessages([ 'collection' => 'This collection cannot be saved.', ]); } } }