forked from moneyphp/money
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Comparator.php
99 lines (85 loc) · 3.35 KB
/
Comparator.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
<?php
declare(strict_types=1);
namespace Money\PHPUnit;
use Money\Currencies\AggregateCurrencies;
use Money\Currencies\BitcoinCurrencies;
use Money\Currencies\ISOCurrencies;
use Money\Formatter\IntlMoneyFormatter;
use Money\Money;
use NumberFormatter;
use ReflectionMethod;
use SebastianBergmann\Comparator\ComparisonFailure;
use function assert;
use function method_exists;
/**
* The comparator is for comparing Money objects in PHPUnit tests.
*
* Add this to your bootstrap file:
*
* \SebastianBergmann\Comparator\Factory::getInstance()->register(new \Money\PHPUnit\Comparator());
*
* @internal do not use within your sources: this comparator is only to be used within the test suite of this library
*
* @psalm-suppress PropertyNotSetInConstructor the parent implementation includes factories that cannot be initialized here
* @psalm-suppress DirectConstructorCall
*/
final class Comparator extends \SebastianBergmann\Comparator\Comparator
{
private bool $isComparatorVersion5;
private IntlMoneyFormatter $formatter;
public function __construct()
{
// PHPUnit 10 + sebastian/comparator:5 remove the parent class
// constructor. Call conditionally if detected to keep working on
// previous versions.
if (method_exists(parent::class, '__construct')) {
parent::__construct();
}
// Similarly, comparator:5 changed the constructor signature of
// ComparisonFailure. This needs to be detected so the correct version
// can be used depending on installed tools.
$cfConstructor = new ReflectionMethod(ComparisonFailure::class, '__construct');
$parameterCount = $cfConstructor->getNumberOfParameters();
$this->isComparatorVersion5 = $parameterCount === 5;
$currencies = new AggregateCurrencies([
new ISOCurrencies(),
new BitcoinCurrencies(),
]);
$numberFormatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);
$this->formatter = new IntlMoneyFormatter($numberFormatter, $currencies);
}
/** {@inheritDoc} */
public function accepts(mixed $expected, mixed $actual): bool
{
return $expected instanceof Money && $actual instanceof Money;
}
/**
* {@inheritDoc}
*
* @param float $delta
* @param bool $canonicalize
* @param bool $ignoreCase
*/
public function assertEquals(
mixed $expected,
mixed $actual,
$delta = 0.0,
$canonicalize = false,
$ignoreCase = false
): void {
assert($expected instanceof Money);
assert($actual instanceof Money);
if (! $expected->equals($actual)) {
// Handle signature change in different versions; see notes in
// constructor.
if ($this->isComparatorVersion5) {
throw new ComparisonFailure($expected, $actual, $this->formatter->format($expected), $this->formatter->format($actual), 'Failed asserting that two Money objects are equal.');
}
/**
* @psalm-suppress TooManyArguments
* @psalm-suppress InvalidArgument
*/
throw new ComparisonFailure($expected, $actual, $this->formatter->format($expected), $this->formatter->format($actual), false, 'Failed asserting that two Money objects are equal.');
}
}
}