From 777b2a941450a8c86b9ecf1537675e8e6a2d8b85 Mon Sep 17 00:00:00 2001 From: Thierry Bugier Date: Thu, 11 Jun 2026 08:46:58 +0200 Subject: [PATCH] fix: bad handling of volume, may lead to huge numbers --- src/Toolbox.php | 86 +++++++++++++++++++++---------------- tests/units/ToolboxTest.php | 62 ++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 37 deletions(-) diff --git a/src/Toolbox.php b/src/Toolbox.php index eb0ae2d0..7892b665 100644 --- a/src/Toolbox.php +++ b/src/Toolbox.php @@ -232,11 +232,10 @@ public function getDefaultCarbonIntensityDownloadDate(): DateTimeImmutable /** * Format a weight passing a weight in grams * - * @param float $weight Weight in grams - * + * @param float $v Weight in grams * @return string formatted weight **/ - public static function getWeight(float $weight): string + public static function getWeight(float $v): string { //TRANS: list of unit (o for octet) $units = [ @@ -252,28 +251,17 @@ public static function getWeight(float $weight): string __('Zt', 'carbon'), __('Yt', 'carbon'), ]; - $multiple = 990; - foreach ($units as $human_readable_unit) { - if ($weight < $multiple) { - break; - } - $weight /= 1000; - } - - $weight = self::dynamicRound($weight); - - //TRANS: %1$s is a number maybe float or string and %2$s the unit - return sprintf(__('%1$s %2$s'), $weight, $human_readable_unit); + return self::scaleNumber($v, $units); } /** * Format a power passing a power in grams * - * @param float $p Power in Watt + * @param float $v Power in Watt * * @return string formatted power **/ - public static function getPower(float $p): string + public static function getPower(float $v): string { //TRANS: list of unit (W for watt) $units = [ @@ -287,28 +275,17 @@ public static function getPower(float $p): string __('ZW', 'carbon'), __('YW', 'carbon'), ]; - $multiple = 990; - foreach ($units as $human_readable_unit) { - if ($p < $multiple) { - break; - } - $p /= 1000; - } - - $p = self::dynamicRound($p); - - //TRANS: %1$s is a number maybe float or string and %2$s the unit - return sprintf(__('%1$s %2$s'), $p, $human_readable_unit); + return self::scaleNumber($v, $units); } /** * Format a energy in watt.hour * - * @param float $p Energy in watt.hour + * @param float $v Energy in watt.hour * * @return string formatted energy **/ - public static function getEnergy(float $p): string + public static function getEnergy($v): string { //TRANS: list of unit (Wh for watt.hour) $units = [ @@ -322,18 +299,53 @@ public static function getEnergy(float $p): string __('ZWh', 'carbon'), __('YWh', 'carbon'), ]; + return self::scaleNumber($v, $units); + } + + /** + * Format a volume in L + * + * @param float $v Volume in L + * + * @return string formatted volume + **/ + public static function getVolume(float $v): string + { + //TRANS: list of unit + $units = [ + __('L', 'carbon'), + __('m³', 'carbon'), + __('dam³', 'carbon'), + __('hm³', 'carbon'), + __('Km³', 'carbon'), + ]; + return self::scaleNumber($v, $units); + } + + /** + * Format a quantity in a given dimension + * + * @param float $v quantity + * @param array $units multiple units for a dimension + * + * @return string formatted volume + **/ + protected static function scaleNumber(float $v, array $units): string + { $multiple = 990; - foreach ($units as $human_readable_unit) { - if ($p < $multiple) { + $human_readable_unit = reset($units); + foreach ($units as $key => $human_readable_unit) { + if ($v >= $multiple && isset($units[$key + 1])) { + $v /= 1000; + } else { break; } - $p /= 1000; } - $p = self::dynamicRound($p); + $v = self::dynamicRound($v); //TRANS: %1$s is a number maybe float or string and %2$s the unit - return sprintf(__('%1$s %2$s'), $p, $human_readable_unit); + return sprintf(__('%1$s %2$s'), $v, $human_readable_unit); } public static function dynamicRound(float $number): float @@ -370,7 +382,7 @@ public static function getHumanReadableValue(float $value, array $unit): string return self::getEnergy($value) . $unit[1]; case 'm³': // Value is in m^3 - return sprintf(__('%1$s %2$s', 'carbon'), $value * 1000, 'L'); + return self::getVolume($value * 1000) . $unit[1]; case 'mol': break; } diff --git a/tests/units/ToolboxTest.php b/tests/units/ToolboxTest.php index c885e778..62cee2c8 100644 --- a/tests/units/ToolboxTest.php +++ b/tests/units/ToolboxTest.php @@ -585,4 +585,66 @@ public function test_getInfocomLifespanInMonth_returns_interval_from_buy_date_ov $result = Toolbox::getInfocomLifespanInMonth($infocom); $this->assertSame(48, $result); } + + public function testGetVolume() + { + $this->assertEquals('1 L', Toolbox::getVolume(1)); + $this->assertEquals('989 L', Toolbox::getVolume(989)); + $this->assertEquals('0.99 m³', Toolbox::getVolume(990)); + $this->assertEquals('1 m³', Toolbox::getVolume(1000)); + $this->assertEquals('1 dam³', Toolbox::getVolume(1000 * 1000)); + $this->assertEquals('1 hm³', Toolbox::getVolume(1000 * 1000 * 1000)); + $this->assertEquals('1 Km³', Toolbox::getVolume(1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1000 Km³', Toolbox::getVolume(1000 * 1000 * 1000 * 1000 * 1000)); + } + + public function testGetWeight() + { + $this->assertEquals('1 g', Toolbox::getWeight(1)); + $this->assertEquals('989 g', Toolbox::getWeight(989)); + $this->assertEquals('0.99 Kg', Toolbox::getWeight(990)); + $this->assertEquals('1 Kg', Toolbox::getWeight(1000)); + $this->assertEquals('1 t', Toolbox::getWeight(1000 * 1000)); + $this->assertEquals('1 Kt', Toolbox::getWeight(1000 * 1000 * 1000)); + $this->assertEquals('1 Mt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 Gt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 Tt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 Pt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 Et', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 Zt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 Yt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1000 Yt', Toolbox::getWeight(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + } + + public function testGetPower() + { + $this->assertEquals('1 W', Toolbox::getPower(1)); + $this->assertEquals('989 W', Toolbox::getPower(989)); + $this->assertEquals('0.99 KW', Toolbox::getPower(990)); + $this->assertEquals('1 KW', Toolbox::getPower(1000)); + $this->assertEquals('1 MW', Toolbox::getPower(1000 * 1000)); + $this->assertEquals('1 GW', Toolbox::getPower(1000 * 1000 * 1000)); + $this->assertEquals('1 TW', Toolbox::getPower(1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 PW', Toolbox::getPower(1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 EW', Toolbox::getPower(1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 ZW', Toolbox::getPower(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 YW', Toolbox::getPower(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1000 YW', Toolbox::getPower(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + } + + public function testGetEnergy() + { + $this->assertEquals('1 Wh', Toolbox::getEnergy(1)); + $this->assertEquals('989 Wh', Toolbox::getEnergy(989)); + $this->assertEquals('0.99 KWh', Toolbox::getEnergy(990)); + $this->assertEquals('1 KWh', Toolbox::getEnergy(1000)); + $this->assertEquals('1 MWh', Toolbox::getEnergy(1000 * 1000)); + $this->assertEquals('1 GWh', Toolbox::getEnergy(1000 * 1000 * 1000)); + $this->assertEquals('1 TWh', Toolbox::getEnergy(1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 PWh', Toolbox::getEnergy(1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 EWh', Toolbox::getEnergy(1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 ZWh', Toolbox::getEnergy(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1 YWh', Toolbox::getEnergy(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + $this->assertEquals('1000 YWh', Toolbox::getEnergy(1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000 * 1000)); + } }