Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Quick money (butchering this library for the glory of satan, and CPU cycles) #634

Merged
merged 48 commits into from
May 2, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
8eda988
This patch attempts to make quick money out of `moneyphp/money`
Ocramius Apr 13, 2021
5b39800
Adapted PHPUnit tests to comply with the new PHPUnit 9.5+ signatures
Ocramius Apr 13, 2021
df44eed
Removed `symfony/phpunit-bridge`, which is just noise (always has been)
Ocramius Apr 13, 2021
d9c6238
Removed deprecation handler environment variables, now unused
Ocramius Apr 13, 2021
4eafa82
Compatibility with PHPUnit 9.5+ - if we expect deprecations to be rai…
Ocramius Apr 13, 2021
8d25eb5
Added simplistic benchmarks about money instantiation, comparison and…
Ocramius Apr 13, 2021
f004690
Added benchmarks for `Money::sum()`, `Money::min()`, `Money::max()` a…
Ocramius Apr 13, 2021
ca05b46
Added benchmarks for `Number::fromString()`, which is used a lot in n…
Ocramius Apr 13, 2021
fa42867
Run benchmarks as part of `composer test`, to avoid them bit-rotting …
Ocramius Apr 13, 2021
809b12d
Imported global functions to allow OpCache to optimize away well-know…
Ocramius Apr 13, 2021
e094533
Enforcing `Currency#__construct()` to require a `string` as argument,…
Ocramius Apr 13, 2021
b009ce2
Inlined fetching of `Calculator` inside `Money` to avoid calling `get…
Ocramius Apr 13, 2021
f16dbd3
Removed the need to create a `Number` instance in `BcMathCalculator#m…
Ocramius Apr 13, 2021
9bcc47e
Removed `newInstance` private constructor: can be inlined where relevant
Ocramius Apr 13, 2021
25602b9
Simplified `Money#equals()` to only check currency equality when amou…
Ocramius Apr 13, 2021
8c8639c
Directly checking equality of two currencies at engine level
Ocramius Apr 13, 2021
ecdce7d
Removed `func_num_args()` magic method logic, replaced by inlined `co…
Ocramius Apr 13, 2021
57bb76f
In `BcMathCalculator`, removing the need to cast to a `Number` when r…
Ocramius Apr 13, 2021
b582575
Correctly referencing `self::parseFractionalPart()` from within `Numb…
Ocramius Apr 13, 2021
1f838b7
When the engine supports an integer value, use a simple `(string) (in…
Ocramius Apr 13, 2021
8cdbb66
Removed `assertOperand()`, since we can ensure that a `numeric-string…
Ocramius Apr 13, 2021
5298583
Removed `assertRoundingMode()`, which can be enforced at type level, …
Ocramius Apr 13, 2021
48e765f
Simplified `Number::fromString()` to internally use `explode()` inste…
Ocramius Apr 13, 2021
e1e091c
Bumping to PHP 8 minimum as per convo with @frederikbosch @ https://g…
Ocramius Apr 15, 2021
7462d54
Upgraded sources to PHP 8 type declarations, reworked internal number…
Ocramius Apr 15, 2021
a2c2554
Brought type inference to 100% of the codebase (tests still missing)
Ocramius Apr 15, 2021
0d1ec59
Commit current `composer.lock` to make builds more stable
Ocramius Apr 16, 2021
f2890ba
Applied detailed type-checking to the unit test suite
Ocramius Apr 16, 2021
0c7d705
Stricter type checks around invalid operands, hunting down unused/red…
Ocramius Apr 16, 2021
796bd9c
Applied automated CS fixes, improved github actions setup to run psal…
Ocramius Apr 16, 2021
6cc8a20
Removed phpstan and phpspec dependencies that are not in use
Ocramius Apr 16, 2021
b815e26
Added `roave/infection-static-analysis-plugin` and configured a minim…
Ocramius Apr 16, 2021
6a5dcd1
Hunted down a few easy-fix mutants that were just about migrating php…
Ocramius Apr 16, 2021
2d359ac
Made calculators completely inflexible and static
Ocramius Apr 16, 2021
6504e33
Documented hat a type-checker is pretty much required when using this…
Ocramius Apr 16, 2021
6fb8f8c
Sorted `scripts` section in `composer.json` to comply with `ergebnis/…
Ocramius Apr 16, 2021
61fa7b4
Removed prophecy mocks from phpunit tests, removed `phpspec/prophecy-…
Ocramius Apr 16, 2021
0689d3c
Updated `MoneyFactory` static methods to require `numeric-string|int`…
Ocramius Apr 16, 2021
7876b8f
Restricted test coverage to individual tested units of code
Ocramius Apr 16, 2021
dc3ce62
Moved division- and modulo-by-zero exception throwing into the `Calcu…
Ocramius Apr 22, 2021
9758d5f
Removed `is_int()` check on `$amount` passed to `Money` constructor
Ocramius Apr 22, 2021
7790e52
Removed `PhpCalculator`: since we require `ext-bcmath`, there is no n…
Ocramius Apr 22, 2021
eb32c53
Removed unused `Money::fromFloat()`, since we no longer operate with …
Ocramius Apr 22, 2021
9496d09
Replaced `(float)` cast with `sprintf('%.14F', ...)`, as it is more p…
Ocramius Apr 22, 2021
91c8091
Removd test reference to `Number::fromFloat()` (no longer existing)
Ocramius Apr 22, 2021
756649c
Revert removal of `Money::fromFloat()`
Ocramius Apr 23, 2021
8e0630f
Rewrote `AggregateCurrencies` to use a rewindable `AppendIterator` in…
Ocramius Apr 23, 2021
8df0b26
Use assertions statically (since they are declared as static methods …
Ocramius Apr 23, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 0 additions & 15 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,13 +51,6 @@
</errorLevel>
</InternalMethod>

<InvalidOperand>
<errorLevel type="suppress">
<!-- The PhpCalculator is designed to operate with risky/internal math operations -->
<file name="src/Calculator/PhpCalculator.php"/>
</errorLevel>
</InvalidOperand>

<PossiblyUnusedMethod>
<errorLevel type="suppress">
<!-- calculators are not swapped at runtime in our test suite - they are a dead/deprecated concept
Expand All @@ -66,14 +59,6 @@
<referencedMethod name="Money\Money::registerCalculator"/>
</errorLevel>
</PossiblyUnusedMethod>

<UnusedMethodCall>
<errorLevel type="suppress">
<!-- the PHP calculator contains runtime assertions, since we're operating under limited
system resources (32bit or 64bit integers) rather than with full fixed point arithmetic -->
<file name="src/Calculator/PhpCalculator.php"/>
</errorLevel>
</UnusedMethodCall>
</issueHandlers>

<plugins>
Expand Down
38 changes: 0 additions & 38 deletions spec/Calculator/PhpCalculatorSpec.php

This file was deleted.

8 changes: 0 additions & 8 deletions spec/NumberSpec.php
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,4 @@ public function it_throws_an_exception_when_number_is_invalid(): void

$this->shouldThrow(InvalidArgumentException::class)->duringInstantiation();
}

public function it_creates_a_number_from_float(): void
{
$number = $this->fromFloat(1.1);

$number->shouldHaveType(Number::class);
$number->__toString()->shouldReturn('1.1');
}
}
8 changes: 6 additions & 2 deletions src/Calculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

namespace Money;

use Money\Exception\InvalidArgumentException;

/**
* Money calculations abstracted away from the Money value object.
*
Expand Down Expand Up @@ -70,6 +72,8 @@ public static function multiply(string $amount, string $multiplier): string;
*
* @psalm-return numeric-string
*
* @throws InvalidArgumentException when $divisor is zero.
*
* @psalm-pure
*/
public static function divide(string $amount, string $divisor): string;
Expand Down Expand Up @@ -140,9 +144,9 @@ public static function share(string $amount, string $ratio, string $total): stri
*
* @psalm-return numeric-string
*
* @psalm-pure
* @throws InvalidArgumentException when $divisor is zero.
*
* @TODO what to do with $divisor == '0'?
* @psalm-pure
*/
public static function mod(string $amount, string $divisor): string;
}
14 changes: 11 additions & 3 deletions src/Calculator/BcMathCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace Money\Calculator;

use InvalidArgumentException;
use InvalidArgumentException as CoreInvalidArgumentException;
use Money\Calculator;
use Money\Exception\InvalidArgumentException;
use Money\Money;
use Money\Number;

Expand Down Expand Up @@ -48,6 +49,10 @@ public static function multiply(string $amount, string $multiplier): string
/** @psalm-pure */
public static function divide(string $amount, string $divisor): string
{
if (bccomp($divisor, '0', self::SCALE) === 0) {
throw InvalidArgumentException::divisionByZero();
}

return bcdiv($amount, $divisor, self::SCALE);
}

Expand Down Expand Up @@ -176,7 +181,7 @@ public static function round(string $number, int $roundingMode): string
);
}

throw new InvalidArgumentException('Unknown rounding mode');
throw new CoreInvalidArgumentException('Unknown rounding mode');
}

/**
Expand Down Expand Up @@ -206,7 +211,10 @@ public static function share(string $amount, string $ratio, string $total): stri
/** @psalm-pure */
public static function mod(string $amount, string $divisor): string
{
// @TODO: null check needed because `bcmod(_, 0)` fails - should the check be kept in here?
if (bccomp($divisor, '0') === 0) {
throw InvalidArgumentException::moduloByZero();
}

return bcmod($amount, $divisor) ?? '0';
}
}
21 changes: 18 additions & 3 deletions src/Calculator/GmpCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

namespace Money\Calculator;

use InvalidArgumentException;
use InvalidArgumentException as CoreInvalidArgumentException;
use Money\Calculator;
use Money\Exception\InvalidArgumentException;
use Money\Money;
use Money\Number;

Expand All @@ -27,7 +28,13 @@
use const GMP_ROUND_MINUSINF;
use const STR_PAD_LEFT;

/** @psalm-immutable */
/**
* @psalm-immutable
*
* Important: the {@see GmpCalculator} is not optimized for decimal operations, as GMP
* is designed to operate on large integers. Consider using this only if your
* system does not have `ext-bcmath` installed.
*/
final class GmpCalculator implements Calculator
{
private const SCALE = 14;
Expand Down Expand Up @@ -107,6 +114,10 @@ public static function multiply(string $amount, string $multiplier): string
/** @psalm-pure */
public static function divide(string $amount, string $divisor): string
{
if (self::compare($divisor, '0') === 0) {
throw InvalidArgumentException::moduloByZero();
}

$divisor = Number::fromString($divisor);

if ($divisor->isDecimal()) {
Expand Down Expand Up @@ -267,7 +278,7 @@ public static function round(string $number, int $roundingMode): string
);
}

throw new InvalidArgumentException('Unknown rounding mode');
throw new CoreInvalidArgumentException('Unknown rounding mode');
}

/**
Expand Down Expand Up @@ -296,6 +307,10 @@ public static function share(string $amount, string $ratio, string $total): stri
/** @psalm-pure */
public static function mod(string $amount, string $divisor): string
{
if (self::compare($divisor, '0') === 0) {
throw InvalidArgumentException::moduloByZero();
}

// gmp_mod() only calculates non-negative integers, so we use absolutes
$remainder = gmp_mod(self::absolute($amount), self::absolute($divisor));

Expand Down
Loading