@@ -76,45 +76,48 @@ public static function recordVisit(int $userId, int $teamId, string $url, string
7676
7777 public static function togglePin (int $ userId , int $ teamId , string $ url ): bool
7878 {
79- $ record = self ::where ('user_id ' , $ userId )
80- ->where ('team_id ' , $ teamId )
81- ->first ();
79+ return \DB ::transaction (function () use ($ userId , $ teamId , $ url ) {
80+ $ record = self ::where ('user_id ' , $ userId )
81+ ->where ('team_id ' , $ teamId )
82+ ->lockForUpdate ()
83+ ->first ();
84+
85+ if (! $ record ) {
86+ return false ;
87+ }
8288
83- if (! $ record ) {
84- return false ;
85- }
89+ $ pages = collect ($ record ->pages );
90+ $ index = $ pages ->search (fn ($ p ) => $ p ['url ' ] === $ url );
8691
87- $ pages = collect ($ record ->pages );
88- $ index = $ pages ->search (fn ($ p ) => $ p ['url ' ] === $ url );
89-
90- if ($ index === false ) {
91- return false ;
92- }
92+ if ($ index === false ) {
93+ return false ;
94+ }
9395
94- $ page = $ pages [$ index ];
95- $ currentlyPinned = $ page ['pinned ' ] ?? false ;
96+ $ page = $ pages [$ index ];
97+ $ currentlyPinned = $ page ['pinned ' ] ?? false ;
9698
97- // Check if we can pin (max 5 pinned)
98- if (! $ currentlyPinned ) {
99- $ pinnedCount = $ pages ->filter (fn ($ p ) => ! empty ($ p ['pinned ' ]))->count ();
100- if ($ pinnedCount >= 5 ) {
101- return false ; // Can't pin more
99+ // Check if we can pin (max 5 pinned)
100+ if (! $ currentlyPinned ) {
101+ $ pinnedCount = $ pages ->filter (fn ($ p ) => ! empty ($ p ['pinned ' ]))->count ();
102+ if ($ pinnedCount >= 5 ) {
103+ return false ; // Can't pin more
104+ }
102105 }
103- }
104106
105- $ page ['pinned ' ] = ! $ currentlyPinned ;
106- $ page ['pinned_at ' ] = $ page ['pinned ' ] ? now ()->toISOString () : null ;
107+ $ page ['pinned ' ] = ! $ currentlyPinned ;
108+ $ page ['pinned_at ' ] = $ page ['pinned ' ] ? now ()->toISOString () : null ;
107109
108- $ pages [$ index ] = $ page ;
110+ $ pages [$ index ] = $ page ;
109111
110- // Re-sort: pinned first (by pinned_at desc), then unpinned (by visited_at desc)
111- $ pinned = $ pages ->filter (fn ($ p ) => ! empty ($ p ['pinned ' ]))->sortByDesc ('pinned_at ' );
112- $ unpinned = $ pages ->reject (fn ($ p ) => ! empty ($ p ['pinned ' ]))->sortByDesc ('visited_at ' );
112+ // Re-sort: pinned first (by pinned_at desc), then unpinned (by visited_at desc)
113+ $ pinned = $ pages ->filter (fn ($ p ) => ! empty ($ p ['pinned ' ]))->sortByDesc ('pinned_at ' );
114+ $ unpinned = $ pages ->reject (fn ($ p ) => ! empty ($ p ['pinned ' ]))->sortByDesc ('visited_at ' );
113115
114- $ record ->pages = $ pinned ->merge ($ unpinned )->values ()->all ();
115- $ record ->save ();
116+ $ record ->pages = $ pinned ->merge ($ unpinned )->values ()->all ();
117+ $ record ->save ();
116118
117- return $ page ['pinned ' ];
119+ return $ page ['pinned ' ];
120+ });
118121 }
119122
120123 public static function getRecent (int $ userId , int $ teamId ): array
0 commit comments