[4.x] Upgrade brick/math to support versions ^0.14–^0.17 (#638)

This commit is contained in:
Antonio del Olmo
2026-04-28 00:11:13 +02:00
committed by GitHub
parent 3d1c6d9578
commit 1a1f98b037
11 changed files with 146 additions and 48 deletions
+1 -1
View File
@@ -10,7 +10,7 @@
],
"require": {
"php": "^8.0",
"brick/math": "^0.8.16 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13 || ^0.14",
"brick/math": ">=0.8.16 <=0.17",
"ramsey/collection": "^1.2 || ^2.0"
},
"require-dev": {
Generated
+8 -9
View File
@@ -4,27 +4,26 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "bb087ab286c5dc749e589e7bb6eb96c1",
"content-hash": "d67e7c6f49a1cb1105b75ffd24d2a49d",
"packages": [
{
"name": "brick/math",
"version": "0.14.1",
"version": "0.17.0",
"source": {
"type": "git",
"url": "https://github.com/brick/math.git",
"reference": "f05858549e5f9d7bb45875a75583240a38a281d0"
"reference": "a62af7ab2e3cee9f9bf4cf77a5d1e6ba408a44ee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/brick/math/zipball/f05858549e5f9d7bb45875a75583240a38a281d0",
"reference": "f05858549e5f9d7bb45875a75583240a38a281d0",
"url": "https://api.github.com/repos/brick/math/zipball/a62af7ab2e3cee9f9bf4cf77a5d1e6ba408a44ee",
"reference": "a62af7ab2e3cee9f9bf4cf77a5d1e6ba408a44ee",
"shasum": ""
},
"require": {
"php": "^8.2"
},
"require-dev": {
"php-coveralls/php-coveralls": "^2.2",
"phpstan/phpstan": "2.1.22",
"phpunit/phpunit": "^11.5"
},
@@ -56,7 +55,7 @@
],
"support": {
"issues": "https://github.com/brick/math/issues",
"source": "https://github.com/brick/math/tree/0.14.1"
"source": "https://github.com/brick/math/tree/0.17.0"
},
"funding": [
{
@@ -64,7 +63,7 @@
"type": "github"
}
],
"time": "2025-11-24T14:40:29+00:00"
"time": "2026-03-17T12:54:54+00:00"
},
{
"name": "ramsey/collection",
@@ -5930,5 +5929,5 @@
"php": "^8.0"
},
"platform-dev": {},
"plugin-api-version": "2.6.0"
"plugin-api-version": "2.9.0"
}
+1
View File
@@ -2,6 +2,7 @@ parameters:
tmpDir: ./build/cache/phpstan
level: max
treatPhpDocTypesAsCertain: false
reportUnmatchedIgnoredErrors: false
paths:
- ./src
- ./tests
@@ -34,6 +34,7 @@ class GenericNumberConverter implements NumberConverterInterface
*/
public function fromHex(string $hex): string
{
/** @var non-empty-string $hex */
return $this->calculator->fromBase($hex, 16)->toString();
}
+5 -29
View File
@@ -17,7 +17,6 @@ namespace Ramsey\Uuid\Math;
use Brick\Math\BigDecimal;
use Brick\Math\BigInteger;
use Brick\Math\Exception\MathException;
use Brick\Math\RoundingMode as BrickMathRounding;
use Ramsey\Uuid\Exception\InvalidArgumentException;
use Ramsey\Uuid\Type\Decimal;
use Ramsey\Uuid\Type\Hexadecimal;
@@ -31,19 +30,6 @@ use Ramsey\Uuid\Type\NumberInterface;
*/
final class BrickMathCalculator implements CalculatorInterface
{
private const ROUNDING_MODE_MAP = [
RoundingMode::UNNECESSARY => BrickMathRounding::UNNECESSARY,
RoundingMode::UP => BrickMathRounding::UP,
RoundingMode::DOWN => BrickMathRounding::DOWN,
RoundingMode::CEILING => BrickMathRounding::CEILING,
RoundingMode::FLOOR => BrickMathRounding::FLOOR,
RoundingMode::HALF_UP => BrickMathRounding::HALF_UP,
RoundingMode::HALF_DOWN => BrickMathRounding::HALF_DOWN,
RoundingMode::HALF_CEILING => BrickMathRounding::HALF_CEILING,
RoundingMode::HALF_FLOOR => BrickMathRounding::HALF_FLOOR,
RoundingMode::HALF_EVEN => BrickMathRounding::HALF_EVEN,
];
public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface
{
$sum = BigInteger::of($augend->toString());
@@ -87,7 +73,7 @@ final class BrickMathCalculator implements CalculatorInterface
NumberInterface ...$divisors,
): NumberInterface {
/** @phpstan-ignore possiblyImpure.methodCall */
$brickRounding = $this->getBrickRoundingMode($roundingMode);
$brickRounding = BrickMathRoundingMode::resolve($roundingMode);
$quotient = BigDecimal::of($dividend->toString());
@@ -111,8 +97,8 @@ final class BrickMathCalculator implements CalculatorInterface
return new IntegerObject((string) BigInteger::fromBase($value, $base));
} catch (MathException | \InvalidArgumentException $exception) {
throw new InvalidArgumentException(
$exception->getMessage(),
(int) $exception->getCode(),
$exception->getMessage(), /** @phpstan-ignore possiblyImpure.methodCall */
(int) $exception->getCode(), /** @phpstan-ignore possiblyImpure.methodCall */
$exception
);
}
@@ -124,8 +110,8 @@ final class BrickMathCalculator implements CalculatorInterface
return BigInteger::of($value->toString())->toBase($base);
} catch (MathException | \InvalidArgumentException $exception) {
throw new InvalidArgumentException(
$exception->getMessage(),
(int) $exception->getCode(),
$exception->getMessage(), /** @phpstan-ignore possiblyImpure.methodCall */
(int) $exception->getCode(), /** @phpstan-ignore possiblyImpure.methodCall */
$exception
);
}
@@ -141,14 +127,4 @@ final class BrickMathCalculator implements CalculatorInterface
{
return $this->fromBase($value->toString(), 16);
}
/**
* Maps ramsey/uuid rounding modes to those used by brick/math
*
* @return BrickMathRounding::*
*/
private function getBrickRoundingMode(int $roundingMode)
{
return self::ROUNDING_MODE_MAP[$roundingMode] ?? BrickMathRounding::UNNECESSARY;
}
}
+60
View File
@@ -0,0 +1,60 @@
<?php
/**
* This file is part of the ramsey/uuid library
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*
* @copyright Copyright (c) Ben Ramsey <ben@benramsey.com>
* @license http://opensource.org/licenses/MIT MIT
*/
declare(strict_types=1);
namespace Ramsey\Uuid\Math;
use Brick\Math\RoundingMode as BrickMathRounding;
/**
* @internal Polyfill for Brick\Math\RoundingMode constant naming
* changes introduced in brick/math 0.15 (UPPER_SNAKE_CASE → PascalCase)
*/
final class BrickMathRoundingMode
{
/**
* Maps ramsey/uuid rounding mode constants to their PascalCase (>= 0.15)
* and UPPER_SNAKE_CASE (< 0.15) equivalents in brick/math
*/
private const ROUNDING_MODE_MAP = [
RoundingMode::UNNECESSARY => ['Unnecessary', 'UNNECESSARY'],
RoundingMode::UP => ['Up', 'UP'],
RoundingMode::DOWN => ['Down', 'DOWN'],
RoundingMode::CEILING => ['Ceiling', 'CEILING'],
RoundingMode::FLOOR => ['Floor', 'FLOOR'],
RoundingMode::HALF_UP => ['HalfUp', 'HALF_UP'],
RoundingMode::HALF_DOWN => ['HalfDown', 'HALF_DOWN'],
RoundingMode::HALF_CEILING => ['HalfCeiling', 'HALF_CEILING'],
RoundingMode::HALF_FLOOR => ['HalfFloor', 'HALF_FLOOR'],
RoundingMode::HALF_EVEN => ['HalfEven', 'HALF_EVEN'],
];
/**
* Resolves a ramsey/uuid rounding mode to the correct
* Brick\Math\RoundingMode value for the installed version.
*
* @return BrickMathRounding::*
*/
public static function resolve(int $roundingMode)
{
[$pascal, $snake] = self::ROUNDING_MODE_MAP[$roundingMode]
?? self::ROUNDING_MODE_MAP[RoundingMode::UNNECESSARY];
$class = BrickMathRounding::class;
/** @var BrickMathRounding::* */
return defined("$class::$pascal")
? constant("$class::$pascal")
: constant("$class::$snake");
}
}
+4 -4
View File
@@ -65,7 +65,7 @@ interface CalculatorInterface
* Returns the quotient of the provided parameters divided left-to-right
*
* @param int $roundingMode The RoundingMode constant to use for this operation
* @param int $scale The scale to use for this operation
* @param int<0, max> $scale The scale to use for this operation
* @param NumberInterface $dividend The integer to be divided
* @param NumberInterface ...$divisors The integers to divide $dividend by, in the order in which the division
* operations should take place (left-to-right)
@@ -84,8 +84,8 @@ interface CalculatorInterface
/**
* Converts a value from an arbitrary base to a base-10 integer value
*
* @param string $value The value to convert
* @param int $base The base to convert from (i.e., 2, 16, 32, etc.)
* @param non-empty-string $value The value to convert
* @param int<2, 36> $base The base to convert from (i.e., 2, 16, 32, etc.)
*
* @return IntegerObject The base-10 integer value of the converted value
*
@@ -97,7 +97,7 @@ interface CalculatorInterface
* Converts a base-10 integer value to an arbitrary base
*
* @param IntegerObject $value The integer value to convert
* @param int $base The base to convert to (i.e., 2, 16, 32, etc.)
* @param int<2, 36> $base The base to convert to (i.e., 2, 16, 32, etc.)
*
* @return string The value represented in the specified base
*
@@ -15,7 +15,7 @@ class BigNumberConverterTest extends TestCase
$converter = new BigNumberConverter();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('"." is not a valid character in base 16');
$this->expectExceptionMessageMatches('/"\." is not (a )?valid (character )?in base 16/');
$converter->fromHex('123.34');
}
+2 -1
View File
@@ -96,7 +96,7 @@ class BrickMathCalculatorTest extends TestCase
$calculator = new BrickMathCalculator();
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('"o" is not a valid character in base 16');
$this->expectExceptionMessageMatches('/"o" is not (a )?valid (character )?in base 16/');
$calculator->fromBase('foobar', 16);
}
@@ -108,6 +108,7 @@ class BrickMathCalculatorTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Base 1024 is out of range [2, 36]');
/** @phpstan-ignore argument.type */
$calculator->toBase(new IntegerObject(42), 1024);
}
}
+57
View File
@@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace Ramsey\Uuid\Test\Math;
use Brick\Math\RoundingMode as BrickMathRounding;
use Ramsey\Uuid\Math\BrickMathRoundingMode;
use Ramsey\Uuid\Math\RoundingMode;
use Ramsey\Uuid\Test\TestCase;
class BrickMathRoundingModeTest extends TestCase
{
/**
* @dataProvider roundingModeProvider
*/
public function testResolveReturnsValidBrickMathRoundingMode(int $ramseyMode, string $expectedName): void
{
$result = BrickMathRoundingMode::resolve($ramseyMode);
$this->assertTrue(
defined(BrickMathRounding::class . '::' . $expectedName),
"Expected constant Brick\\Math\\RoundingMode::$expectedName to exist",
);
$this->assertSame(constant(BrickMathRounding::class . '::' . $expectedName), $result);
}
/**
* @return array<string, array{int, string}>
*/
public static function roundingModeProvider(): array
{
$usesPascalCase = defined(BrickMathRounding::class . '::Unnecessary');
return [
'UNNECESSARY' => [RoundingMode::UNNECESSARY, $usesPascalCase ? 'Unnecessary' : 'UNNECESSARY'],
'UP' => [RoundingMode::UP, $usesPascalCase ? 'Up' : 'UP'],
'DOWN' => [RoundingMode::DOWN, $usesPascalCase ? 'Down' : 'DOWN'],
'CEILING' => [RoundingMode::CEILING, $usesPascalCase ? 'Ceiling' : 'CEILING'],
'FLOOR' => [RoundingMode::FLOOR, $usesPascalCase ? 'Floor' : 'FLOOR'],
'HALF_UP' => [RoundingMode::HALF_UP, $usesPascalCase ? 'HalfUp' : 'HALF_UP'],
'HALF_DOWN' => [RoundingMode::HALF_DOWN, $usesPascalCase ? 'HalfDown' : 'HALF_DOWN'],
'HALF_CEILING' => [RoundingMode::HALF_CEILING, $usesPascalCase ? 'HalfCeiling' : 'HALF_CEILING'],
'HALF_FLOOR' => [RoundingMode::HALF_FLOOR, $usesPascalCase ? 'HalfFloor' : 'HALF_FLOOR'],
'HALF_EVEN' => [RoundingMode::HALF_EVEN, $usesPascalCase ? 'HalfEven' : 'HALF_EVEN'],
];
}
public function testResolveDefaultsToUnnecessaryForUnknownMode(): void
{
$result = BrickMathRoundingMode::resolve(999);
$expectedName = defined(BrickMathRounding::class . '::Unnecessary') ? 'Unnecessary' : 'UNNECESSARY';
$this->assertSame(constant(BrickMathRounding::class . '::' . $expectedName), $result);
}
}
+6 -3
View File
@@ -6,7 +6,6 @@ namespace Ramsey\Uuid\Test;
use BadMethodCallException;
use Brick\Math\BigDecimal;
use Brick\Math\RoundingMode;
use DateTimeImmutable;
use DateTimeInterface;
use Mockery;
@@ -28,6 +27,8 @@ use Ramsey\Uuid\Generator\RandomGeneratorFactory;
use Ramsey\Uuid\Generator\RandomGeneratorInterface;
use Ramsey\Uuid\Guid\Guid;
use Ramsey\Uuid\Lazy\LazyUuidFromString;
use Ramsey\Uuid\Math\BrickMathRoundingMode;
use Ramsey\Uuid\Math\RoundingMode;
use Ramsey\Uuid\Provider\Node\RandomNodeProvider;
use Ramsey\Uuid\Provider\Time\FixedTimeProvider;
use Ramsey\Uuid\Rfc4122\Fields;
@@ -1214,8 +1215,10 @@ class UuidTest extends TestCase
);
// Assert that the time matches
$usecAdd = BigDecimal::of($usec)->dividedBy('1000000', 14, RoundingMode::HALF_UP);
$testTime = BigDecimal::of($currentTime)->plus($usecAdd)->toScale(0, RoundingMode::DOWN);
$halfUp = BrickMathRoundingMode::resolve(RoundingMode::HALF_UP);
$down = BrickMathRoundingMode::resolve(RoundingMode::DOWN);
$usecAdd = BigDecimal::of($usec)->dividedBy('1000000', 14, $halfUp);
$testTime = BigDecimal::of($currentTime)->plus($usecAdd)->toScale(0, $down);
$this->assertSame((string) $testTime, (string) $uuid64->getDateTime()->getTimestamp());
$this->assertSame((string) $testTime, (string) $uuid32->getDateTime()->getTimestamp());
}