Warenkorb: nicht-numerische Mengen brechen die Gewichtsberechnung nicht mehr
Yard::weight() multiplizierte Gewicht und Menge ohne Cast. Beide Werte stammen aus Session- bzw. Request-Daten; ein fuehrend-numerischer String wie "2,5" loeste unter PHP 8 die ErrorException "A non-numeric value encountered" aus. Danach war die Position dauerhaft defekt, da reCalculateShippingPrice() bei jedem Aufruf erneut fehlschlug. Cart::update() setzt die Menge ohne Validierung (anders als setQuantity()). Eintrittspunkte waren das quantity-Feld im Shop-POST sowie das Textfeld fuer die Menge im Backoffice-Warenkorb. - Yard: neue cartItemWeight() mit explizitem int-Cast fuer Gewicht und Menge - CardController: nicht-numerische Mengen werden uebersprungen, Schutz gegen ein quantity-Feld, das kein Array ist - OrderController: nutzt das bereits vorhandene $qty (int) statt $data['qty'] roh Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2e71173c66
commit
384b2dcff1
4 changed files with 82 additions and 5 deletions
|
|
@ -899,8 +899,8 @@ class OrderController extends Controller
|
||||||
Yard::setTax($cartItem->rowId, $product->getTaxWith(Yard::instance('shopping')->getUserCountry()));
|
Yard::setTax($cartItem->rowId, $product->getTaxWith(Yard::instance('shopping')->getUserCountry()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isset($data['qty']) && $data['qty'] > 0) {
|
if ($qty > 0) {
|
||||||
Yard::instance('shopping')->update($cartItem->rowId, $data['qty']);
|
Yard::instance('shopping')->update($cartItem->rowId, $qty);
|
||||||
} else {
|
} else {
|
||||||
// If 0 get the item by qty:1 and remove it
|
// If 0 get the item by qty:1 and remove it
|
||||||
Yard::instance('shopping')->remove($cartItem->rowId);
|
Yard::instance('shopping')->remove($cartItem->rowId);
|
||||||
|
|
|
||||||
|
|
@ -127,7 +127,14 @@ class CardController extends Controller
|
||||||
|
|
||||||
$data = Request::all();
|
$data = Request::all();
|
||||||
if (isset($data['quantity'])) {
|
if (isset($data['quantity'])) {
|
||||||
|
if (! is_array($data['quantity'])) {
|
||||||
|
return back();
|
||||||
|
}
|
||||||
foreach ($data['quantity'] as $rowId => $qty) {
|
foreach ($data['quantity'] as $rowId => $qty) {
|
||||||
|
if (! is_numeric($qty)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
$qty = (int) $qty;
|
||||||
$cartItem = Yard::instance($this->instance)->get($rowId);
|
$cartItem = Yard::instance($this->instance)->get($rowId);
|
||||||
if ($cartItem) {
|
if ($cartItem) {
|
||||||
$product = Product::find($cartItem->id);
|
$product = Product::find($cartItem->id);
|
||||||
|
|
@ -135,7 +142,7 @@ class CardController extends Controller
|
||||||
$qty = 1;
|
$qty = 1;
|
||||||
}
|
}
|
||||||
if ($product) {
|
if ($product) {
|
||||||
$additionalWeight = (int) $product->weight * ((int) $qty - (int) $cartItem->qty);
|
$additionalWeight = (int) $product->weight * ($qty - (int) $cartItem->qty);
|
||||||
if ($additionalWeight > 0 && Yard::instance($this->instance)->exceedsMaxWeight($additionalWeight)) {
|
if ($additionalWeight > 0 && Yard::instance($this->instance)->exceedsMaxWeight($additionalWeight)) {
|
||||||
\Session::flash('alert-error', __('msg.cart_max_weight_reached'));
|
\Session::flash('alert-error', __('msg.cart_max_weight_reached'));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -425,18 +425,28 @@ class Yard extends Cart
|
||||||
{
|
{
|
||||||
$content = $this->getContent();
|
$content = $this->getContent();
|
||||||
$total = $content->reduce(function ($total, CartItem $cartItem) {
|
$total = $content->reduce(function ($total, CartItem $cartItem) {
|
||||||
return $total + ($cartItem->options->weight ? ($cartItem->options->weight * $cartItem->qty) : 0);
|
return $total + $this->cartItemWeight($cartItem);
|
||||||
}, 0);
|
}, 0);
|
||||||
|
|
||||||
return $total;
|
return $total;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gewicht einer Warenkorb-Position in Gramm.
|
||||||
|
* Gewicht und Menge werden explizit gecastet, da beide Werte aus der Session
|
||||||
|
* bzw. aus Request-Daten stammen und dort auch nicht-numerische Strings landen können.
|
||||||
|
*/
|
||||||
|
private function cartItemWeight(CartItem $cartItem): int
|
||||||
|
{
|
||||||
|
return (int) $cartItem->options->weight * (int) $cartItem->qty;
|
||||||
|
}
|
||||||
|
|
||||||
public function weightByFreeShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
|
public function weightByFreeShipping($decimals = null, $decimalPoint = null, $thousandSeperator = null)
|
||||||
{
|
{
|
||||||
$content = $this->getContent();
|
$content = $this->getContent();
|
||||||
$total = $content->reduce(function ($total, CartItem $cartItem) {
|
$total = $content->reduce(function ($total, CartItem $cartItem) {
|
||||||
if ($cartItem->options->no_free_shipping) {
|
if ($cartItem->options->no_free_shipping) {
|
||||||
return $total + ($cartItem->options->weight ? ($cartItem->options->weight * $cartItem->qty) : 0);
|
return $total + $this->cartItemWeight($cartItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $total;
|
return $total;
|
||||||
|
|
|
||||||
60
tests/Feature/YardCartWeightTest.php
Normal file
60
tests/Feature/YardCartWeightTest.php
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
uses(TestCase::class, RefreshDatabase::class);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menge und Gewicht stammen aus Session- bzw. Request-Daten. Landet dort ein
|
||||||
|
* nicht-numerischer String, warf die Gewichtsberechnung in PHP 8 eine
|
||||||
|
* ErrorException ("A non-numeric value encountered").
|
||||||
|
*/
|
||||||
|
describe('Yard Gewichtsberechnung', function () {
|
||||||
|
it('summiert Gewicht mal Menge', function () {
|
||||||
|
$yard = Yard::instance('test-cart-weight');
|
||||||
|
$yard->destroy();
|
||||||
|
|
||||||
|
$yard->add(1, 'A', 2, 10.0, false, false, ['weight' => 500]);
|
||||||
|
$yard->add(2, 'B', 1, 10.0, false, false, ['weight' => 250]);
|
||||||
|
|
||||||
|
expect($yard->weight())->toBe(1250);
|
||||||
|
|
||||||
|
$yard->destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wirft keinen Fehler bei nicht-numerischer Menge im Warenkorb', function () {
|
||||||
|
$yard = Yard::instance('test-cart-weight');
|
||||||
|
$yard->destroy();
|
||||||
|
|
||||||
|
$cartItem = $yard->add(1, 'A', 1, 10.0, false, false, ['weight' => 500]);
|
||||||
|
$yard->update($cartItem->rowId, '2,5');
|
||||||
|
|
||||||
|
expect($yard->weight())->toBe(1000);
|
||||||
|
|
||||||
|
$yard->destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('wirft keinen Fehler bei nicht-numerischem Gewicht im Warenkorb', function () {
|
||||||
|
$yard = Yard::instance('test-cart-weight');
|
||||||
|
$yard->destroy();
|
||||||
|
|
||||||
|
$yard->add(1, 'A', 2, 10.0, false, false, ['weight' => '500 g']);
|
||||||
|
|
||||||
|
expect($yard->weight())->toBe(1000);
|
||||||
|
|
||||||
|
$yard->destroy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('berücksichtigt nur Artikel ohne kostenlosen Versand', function () {
|
||||||
|
$yard = Yard::instance('test-cart-weight');
|
||||||
|
$yard->destroy();
|
||||||
|
|
||||||
|
$yard->add(1, 'A', 2, 10.0, false, false, ['weight' => 500, 'no_free_shipping' => true]);
|
||||||
|
$yard->add(2, 'B', 2, 10.0, false, false, ['weight' => 500, 'no_free_shipping' => false]);
|
||||||
|
|
||||||
|
expect($yard->weightByFreeShipping())->toBe(1000);
|
||||||
|
|
||||||
|
$yard->destroy();
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
Add table
Add a link
Reference in a new issue