PluginProbe
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler / 1.7.1
FluentCart A New Era of eCommerce – Faster, Lighter, and Simpler v1.7.1
1.7.1 1.7.0 1.6.6 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 All 51 releases
← All changes | api/Resource/FrontendResource/CartResource.php +45 -4 1.6.0 → 1.7.1 View file →
@@ -80,8 +80,16 @@
80 80 'variation' => $variation,
81 81 'product' => !$isCustom ? $variation->product : []
82 82 ]);
83 83
84 + // After the filter, not before: this path takes its quantity straight from a
85 + // public URL param, and the filter above can replace it with anything.
86 + $error = CartHelper::validateQuantity($quantity);
87 + if ($error) {
88 + return $error;
89 + }
90 + $quantity = (int)$quantity;
91 +
84 92 if ($variation->payment_type === 'subscription') {
85 93 $quantity = 1;
86 94 }
87 95
@@ -215,11 +223,13 @@
215 223 {
216 224 $itemId = Arr::get($data, 'id');
217 225 $quantity = Arr::get($data, 'quantity', 1);
218 226
219 - if ($quantity <= 0) {
227 + // This path writes cart_data directly instead of going through Cart::addItem().
228 + $error = CartHelper::validateQuantity($quantity);
229 + if ($error) {
220 230 return static::makeErrorResponse([
221 - ['code' => 403, 'message' => __('Quantity can not be negative.', 'fluent-cart')]
231 + ['code' => 403, 'message' => $error->get_error_message()]
222 232 ]);
223 233 }
224 234
225 235 $cart = CartResource::get([
@@ -351,9 +361,21 @@
351 361 ]);
352 362 }
353 363
354 364 if (!$variation) {
355 - return $cart->removeItem($itemId);
365 + // An item already in the cart whose variation row has since
366 + // disappeared (product/variation deleted) is dropped gracefully.
367 + // An id that was never in the cart and resolves to nothing is a
368 + // client error — silently answering "Cart updated successfully"
369 + // hid typos and probing as a 200 no-op.
370 + if ($existingItem !== null) {
371 + return $cart->removeItem($itemId);
372 + }
373 +
374 + return new WP_Error(
375 + 'invalid_item',
376 + __('Invalid item.', 'fluent-cart')
377 + );
356 378 }
357 379
358 380 $soldIndividually = $isCustom
359 381 ? !empty($variation->sold_individually)
@@ -392,9 +414,13 @@
392 414 }
393 415
394 416 $utmData = static::prepareUtmData($data);
395 417 if ($utmData) {
396 - $cart->utm_data = array_merge(is_array($cart->utm_data) ? $cart->utm_data : [], $utmData);
418 + // Replaced, not merged. A cart row is reused across visits, so merging
419 + // key by key accumulated a union of every touch that ever reached it and
420 + // the column stopped describing any single one. The browser has already
421 + // resolved which touch this is, so its block is the answer.
422 + $cart->utm_data = $utmData;
397 423 $cart->save();
398 424 }
399 425
400 426 return $cart;
@@ -565,8 +591,15 @@
565 591 if ($updatedQuantity < 0) {
566 592 $updatedQuantity = 0;
567 593 }
568 594
595 + if ($updatedQuantity > 0 && ($error = CartHelper::validateQuantity($updatedQuantity))) {
596 + return [
597 + 'code' => 'failed',
598 + 'message' => $error->get_error_message()
599 + ];
600 + }
601 +
569 602 if (!$isFilteredItem) {
570 603
571 604 if (!CartHelper::shouldAddItemToCart($productVariation, $updatedQuantity)) {
572 605 return [
@@ -595,8 +628,16 @@
595 628
596 629 if ($quantity < 1) {
597 630 $quantity = 1;
598 631 }
632 +
633 + if ($error = CartHelper::validateQuantity($quantity)) {
634 + return [
635 + 'code' => 'failed',
636 + 'message' => $error->get_error_message()
637 + ];
638 + }
639 +
599 640 if (!$isFilteredItem) {
600 641 if (!CartHelper::shouldAddItemToCart($productVariation, $quantity)) {
601 642 return [
602 643 'code' => 'failed',