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 | app/Http/Controllers/ProductVariationController.php +27 -22 1.6.0 → 1.6.5 View file →
@@ -289,24 +289,26 @@
289 289
290 290 $row = ['id' => $id];
291 291
292 292 if (array_key_exists('item_price', $update)) {
293 - $itemPriceDollar = floatval($update['item_price']);
293 + // Submitted in CENTS. roundCent() normalizes float artifacts
294 + // without scaling; it does not multiply by 100.
295 + $itemPriceCentsIn = floatval($update['item_price']);
294 296 // Reject negative prices outright rather than coerce to 0 —
295 297 // a caller submitting -50 has either bad client logic or
296 298 // hostile intent; either way we should not silently
297 299 // substitute a price they didn't choose.
298 - if ($itemPriceDollar >= 0) {
299 - $row['item_price'] = Helper::toCent($itemPriceDollar);
300 + if ($itemPriceCentsIn >= 0) {
301 + $row['item_price'] = Helper::roundCent($itemPriceCentsIn);
300 302 }
301 303 }
302 304
303 305 if (array_key_exists('compare_price', $update)) {
304 - $comparePriceDollar = floatval($update['compare_price']);
306 + $comparePriceCentsIn = floatval($update['compare_price']);
305 307 // Mirror of the item_price negative guard. compare_price=0
306 308 // is a valid "no discount" sentinel; negative is not.
307 - if ($comparePriceDollar >= 0) {
308 - $comparePriceCents = Helper::toCent($comparePriceDollar);
309 + if ($comparePriceCentsIn >= 0) {
310 + $comparePriceCents = Helper::roundCent($comparePriceCentsIn);
309 311 // Effective item_price (in cents) for the comparison:
310 312 // the new value if this update sets it (and is valid),
311 313 // otherwise the already-persisted value from the DB.
312 314 // Falling back to 0 would re-introduce the bypass
@@ -417,9 +419,9 @@
417 419 $itemPrice = Arr::get($raw, 'item_price');
418 420 if ($itemPrice !== null && $itemPrice !== '') {
419 421 $price = floatval($itemPrice);
420 422 if ($price >= 0) {
421 - $topLevelDelta['item_price'] = Helper::toCent($price);
423 + $topLevelDelta['item_price'] = Helper::roundCent($price);
422 424 }
423 425 }
424 426
425 427 $comparePrice = Arr::get($raw, 'compare_price');
@@ -425,9 +427,9 @@
425 427 $comparePrice = Arr::get($raw, 'compare_price');
426 428 if ($comparePrice !== null && $comparePrice !== '') {
427 429 $compare = floatval($comparePrice);
428 430 if ($compare >= 0) {
429 - $topLevelDelta['_compare_price_dollars'] = $compare;
431 + $topLevelDelta['_compare_price_cents'] = $compare;
430 432 }
431 433 }
432 434
433 435 // SKU uniqueness — only apply to a single variant to avoid duplicates.
@@ -466,9 +468,9 @@
466 468 $itemCost = Arr::get($raw, 'item_cost');
467 469 if ($itemCost !== null && $itemCost !== '') {
468 470 $cost = floatval($itemCost);
469 471 if ($cost >= 0) {
470 - $topLevelDelta['item_cost'] = Helper::toCent($cost);
472 + $topLevelDelta['item_cost'] = Helper::roundCent($cost);
471 473 }
472 474 }
473 475
474 476 $rawOtherInfo = Arr::get($raw, 'other_info');
@@ -479,8 +481,19 @@
479 481 if (empty($topLevelDelta) && ($otherInfoDelta === null || empty($otherInfoDelta))) {
480 482 return $this->sendError(['message' => __('No valid updates provided.', 'fluent-cart')], 422);
481 483 }
482 484
485 + // Setting variants to subscription requires a billing interval in the
486 + // same request — a subscription without one can never bill. Checked
487 + // before the transaction so bad input fails fast with no rollback.
488 + // (An invalid interval was already dropped by sanitizeOtherInfoDelta.)
489 + if (is_array($otherInfoDelta)
490 + && Arr::get($otherInfoDelta, 'payment_type') === 'subscription'
491 + && empty($otherInfoDelta['repeat_interval'])
492 + ) {
493 + return $this->sendError(['message' => __('A valid billing interval is required for subscription variants.', 'fluent-cart')], 422);
494 + }
495 +
483 496 $db = ProductVariation::query()->getConnection();
484 497 $now = gmdate('Y-m-d H:i:s');
485 498 $updatedProductId = 0;
486 499 $batchData = [];
@@ -516,10 +529,10 @@
516 529 if (isset($topLevelDelta['item_price'])) {
517 530 $rowUpdate['item_price'] = $topLevelDelta['item_price'];
518 531 }
519 532
520 - if (isset($topLevelDelta['_compare_price_dollars'])) {
521 - $compareCents = Helper::toCent($topLevelDelta['_compare_price_dollars']);
533 + if (isset($topLevelDelta['_compare_price_cents'])) {
534 + $compareCents = Helper::roundCent($topLevelDelta['_compare_price_cents']);
522 535 $itemPriceCents = isset($rowUpdate['item_price'])
523 536 ? (int) $rowUpdate['item_price']
524 537 : (int) $existingVariant->item_price;
525 538 $rowUpdate['compare_price'] = ($compareCents > 0 && $compareCents >= $itemPriceCents)
@@ -561,18 +574,10 @@
561 574 unset($merged[$subKey]);
562 575 }
563 576 }
564 577
565 - // A subscription row without a billing interval is unusable —
566 - // reject the whole batch (an invalid interval is silently
567 - // dropped by sanitizeOtherInfoDelta, so it can be missing here).
568 - // Runs in the prepare pass: nothing has been written yet.
569 - if ($paymentType === 'subscription' && !Arr::get($merged, 'repeat_interval')) {
570 - $db->rollBack();
571 - return $this->sendError(['message' => __('A valid billing interval is required for subscription variants.', 'fluent-cart')], 422);
572 - }
573 578 if ($paymentType === 'subscription' && array_key_exists('signup_fee', $otherInfoDelta)) {
574 - $merged['signup_fee'] = Helper::toCent(floatval($otherInfoDelta['signup_fee']));
579 + $merged['signup_fee'] = Helper::roundCent($otherInfoDelta['signup_fee']);
575 580 }
576 581
577 582 // `installment` is not an accepted delta key (see sanitizeOtherInfoDelta),
578 583 // so the stored flag on the row decides whether this is an installment
@@ -751,10 +756,10 @@
751 756 }
752 757 $delta[$key] = floatval($value);
753 758 }
754 759
755 - // signup_fee is stored in dollars here; groupBulkUpdate() converts to cents
756 - // via Helper::toCent() when payment_type is subscription.
760 + // signup_fee arrives in cents; groupBulkUpdate() normalizes it with
761 + // Helper::roundCent() when payment_type is subscription.
757 762 $signupFee = Arr::get($raw, 'signup_fee');
758 763 if ($signupFee !== null && $signupFee !== '') {
759 764 $delta['signup_fee'] = floatval($signupFee);
760 765 }