From f70eaae6f5c21d0cbdaabbf1f78e340e4b9455bd Mon Sep 17 00:00:00 2001 From: minimexat Date: Sun, 8 Feb 2026 15:08:58 +0100 Subject: [PATCH] FIX #34342 PHP 8.1 undefined array key warnings in Product::getSellPrice() multiprices (#37144) When using multiprices (PRODUIT_MULTIPRICES or PRODUIT_CUSTOMER_PRICES_AND_MULTIPRICES), getSellPrice() accesses $this->multiprices[$level], multiprices_ttc, multiprices_min, multiprices_min_ttc, and multiprices_base_type arrays using the buyer's price_level as key without checking if the key exists. This causes 'undefined array key' warnings on PHP 8.1+ when a third party has a price_level set but the product doesn't have prices defined for that specific level. Similarly, prices_by_qty array accesses for PRODUIT_CUSTOMER_PRICES_BY_QTY and PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES modes could trigger warnings when the array index doesn't exist. Changes: - Add isset() checks with safe defaults for all multiprices array accesses (0 for prices, 'HT' for price_base_type) - Replace direct prices_by_qty access with !empty() checks Co-authored-by: f-hoedl Co-authored-by: Laurent Destailleur --- htdocs/product/class/product.class.php | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/htdocs/product/class/product.class.php b/htdocs/product/class/product.class.php index 7dfde480933..78c532b6229 100644 --- a/htdocs/product/class/product.class.php +++ b/htdocs/product/class/product.class.php @@ -2420,11 +2420,11 @@ class Product extends CommonObject } if (!$pricebycustomerexist && !empty($thirdparty_buyer->price_level)) { - $pu_ht = $this->multiprices[$thirdparty_buyer->price_level]; - $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level]; - $price_min = $this->multiprices_min[$thirdparty_buyer->price_level]; - $price_min_ttc = $this->multiprices_min_ttc[$thirdparty_buyer->price_level]; - $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level]; + $pu_ht = isset($this->multiprices[$thirdparty_buyer->price_level]) ? $this->multiprices[$thirdparty_buyer->price_level] : 0; + $pu_ttc = isset($this->multiprices_ttc[$thirdparty_buyer->price_level]) ? $this->multiprices_ttc[$thirdparty_buyer->price_level] : 0; + $price_min = isset($this->multiprices_min[$thirdparty_buyer->price_level]) ? $this->multiprices_min[$thirdparty_buyer->price_level] : 0; + $price_min_ttc = isset($this->multiprices_min_ttc[$thirdparty_buyer->price_level]) ? $this->multiprices_min_ttc[$thirdparty_buyer->price_level] : 0; + $price_base_type = isset($this->multiprices_base_type[$thirdparty_buyer->price_level]) ? $this->multiprices_base_type[$thirdparty_buyer->price_level] : 'HT'; if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) { @@ -2439,11 +2439,11 @@ class Product extends CommonObject } } } elseif (getDolGlobalString('PRODUIT_MULTIPRICES') && !empty($thirdparty_buyer->price_level)) { // // If price per segment - $pu_ht = $this->multiprices[$thirdparty_buyer->price_level]; - $pu_ttc = $this->multiprices_ttc[$thirdparty_buyer->price_level]; - $price_min = $this->multiprices_min[$thirdparty_buyer->price_level]; - $price_min_ttc = $this->multiprices_min_ttc[$thirdparty_buyer->price_level]; - $price_base_type = $this->multiprices_base_type[$thirdparty_buyer->price_level]; + $pu_ht = isset($this->multiprices[$thirdparty_buyer->price_level]) ? $this->multiprices[$thirdparty_buyer->price_level] : 0; + $pu_ttc = isset($this->multiprices_ttc[$thirdparty_buyer->price_level]) ? $this->multiprices_ttc[$thirdparty_buyer->price_level] : 0; + $price_min = isset($this->multiprices_min[$thirdparty_buyer->price_level]) ? $this->multiprices_min[$thirdparty_buyer->price_level] : 0; + $price_min_ttc = isset($this->multiprices_min_ttc[$thirdparty_buyer->price_level]) ? $this->multiprices_min_ttc[$thirdparty_buyer->price_level] : 0; + $price_base_type = isset($this->multiprices_base_type[$thirdparty_buyer->price_level]) ? $this->multiprices_base_type[$thirdparty_buyer->price_level] : 'HT'; if (getDolGlobalString('PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL')) { // using this option is a bug. kept for backward compatibility if (isset($this->multiprices_tva_tx[$thirdparty_buyer->price_level])) { @@ -2490,7 +2490,7 @@ class Product extends CommonObject } } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY')) { // If price per quantity - if ($this->prices_by_qty[0]) { + if (!empty($this->prices_by_qty[0])) { // yes, this product has some prices per quantity // Search price into product_price_by_qty from $this->id foreach ($this->prices_by_qty_list[0] as $priceforthequantityarray) { @@ -2508,7 +2508,7 @@ class Product extends CommonObject } } elseif (getDolGlobalString('PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES')) { // If price per quantity and customer - if ($this->prices_by_qty[$thirdparty_buyer->price_level]) { + if (!empty($this->prices_by_qty[$thirdparty_buyer->price_level])) { // yes, this product has some prices per quantity // Search price into product_price_by_qty from $this->id foreach ($this->prices_by_qty_list[$thirdparty_buyer->price_level] as $priceforthequantityarray) {