PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.6.5
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.6.5
1.6.5 1.6.4 1.6.3 1.6.2 1.6.1 1.6.0 1.5.4 1.5.5 1.5.3 1.5.2 1.5.1 1.5.0 1.4.2 1.4.1 1.4.0 1.3.28 1.3.27 1.3.26 1.3.25 1.3.23 1.3.22 1.3.21 1.3.20 1.3.19 trunk All 48 releases
← All changes | api/Resource/FrontendResource/CartResource.php +47 -8 1.5.0 → 1.6.5 View file →
@@ -19,8 +19,29 @@
19 19
20 20 class CartResource extends BaseResourceApi
21 21 {
22 22
23 + /**
24 + * Per-request memo for get(). In production every HTTP request runs in a
25 + * fresh PHP process, so this lives exactly one request. Long-running
26 + * processes that simulate multiple requests (test suites, CLI) must clear
27 + * it between simulated requests via resetCartCache() — as a
28 + * function-static it was unreachable and leaked the first request's cart
29 + * into every subsequent one.
30 + *
31 + * Only a resolved Cart is memoized; a null ("no cart") result is
32 + * deliberately re-queried on the next call — matching the original
33 + * function-static behavior, where isset(null) === false.
34 + *
35 + * @var Cart|null|false false = not resolved yet
36 + */
37 + private static $cartCache = false;
38 +
39 + public static function resetCartCache(): void
40 + {
41 + static::$cartCache = false;
42 + }
43 +
23 44 public static function getQuery(): Builder
24 45 {
25 46 return Cart::query();
26 47 }
@@ -140,11 +161,10 @@
140 161 *
141 162 */
142 163 public static function get(array $params = [])
143 164 {
144 - static $cart;
145 - if (isset($cart)) {
146 - return $cart;
165 + if (static::$cartCache !== false && static::$cartCache !== null) {
166 + return static::$cartCache;
147 167 }
148 168
149 169 $autoCreate = Arr::get($params, 'create', false);
150 170
@@ -159,9 +179,9 @@
159 179 ->where('cart_group', 'instant');
160 180
161 181 $tempCart = $cartQuery->first();
162 182
163 - $cart = $tempCart;
183 + static::$cartCache = $tempCart;
164 184
165 185 if (!$autoCreate) {
166 186 return $tempCart;
167 187 }
@@ -166,11 +186,11 @@
166 186 return $tempCart;
167 187 }
168 188 }
169 189
170 - $cart = static::getOrSetCartForThisDevice($autoCreate);
190 + static::$cartCache = static::getOrSetCartForThisDevice($autoCreate);
171 191
172 - return $cart;
192 + return static::$cartCache;
173 193 }
174 194
175 195 public static function find($id, $params = [])
176 196 {
@@ -331,9 +351,21 @@
331 351 ]);
332 352 }
333 353
334 354 if (!$variation) {
335 - return $cart->removeItem($itemId);
355 + // An item already in the cart whose variation row has since
356 + // disappeared (product/variation deleted) is dropped gracefully.
357 + // An id that was never in the cart and resolves to nothing is a
358 + // client error — silently answering "Cart updated successfully"
359 + // hid typos and probing as a 200 no-op.
360 + if ($existingItem !== null) {
361 + return $cart->removeItem($itemId);
362 + }
363 +
364 + return new WP_Error(
365 + 'invalid_item',
366 + __('Invalid item.', 'fluent-cart')
367 + );
336 368 }
337 369
338 370 $soldIndividually = $isCustom
339 371 ? !empty($variation->sold_individually)
@@ -372,9 +404,13 @@
372 404 }
373 405
374 406 $utmData = static::prepareUtmData($data);
375 407 if ($utmData) {
376 - $cart->utm_data = array_merge(is_array($cart->utm_data) ? $cart->utm_data : [], $utmData);
408 + // Replaced, not merged. A cart row is reused across visits, so merging
409 + // key by key accumulated a union of every touch that ever reached it and
410 + // the column stopped describing any single one. The browser has already
411 + // resolved which touch this is, so its block is the answer.
412 + $cart->utm_data = $utmData;
377 413 $cart->save();
378 414 }
379 415
380 416 return $cart;
@@ -742,12 +778,15 @@
742 778 }
743 779
744 780 $userId = get_current_user_id();
745 781 if ($userId) {
782 + // Latest cart first — without an order, first() picks by primary key
783 + // (cart_hash), which resurrects an arbitrary old cart for the user.
746 784 $cart = static::getQuery()
747 785 ->where('user_id', $userId)
748 786 ->where('stage', '!=', 'completed')
749 787 ->where('cart_group', 'global')
788 + ->orderBy('updated_at', 'DESC')
750 789 ->first();
751 790
752 791 if ($cart) {
753 792 return $cart;