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

#87 - Allow static macros #88

Merged
merged 2 commits into from
Jul 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
70 changes: 70 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,76 @@ or
<x-currency currency="USD" />
```

### Macros

This package implements the Laravel `Macroable` trait, allowing macros and mixins on both `Money` and `Currency`.

Example use case:

```php
use Akaunting\Money\Currency;
use Akaunting\Money\Money;

Money::macro(
'absolute',
fn () => $this->isPositive() ? $this : $this->multiply(-1)
);

$money = Money::USD(1000)->multiply(-1);

$absolute = $money->absolute();
```

Macros can be called statically too:

```php
use Akaunting\Money\Currency;
use Akaunting\Money\Money;

Money::macro('zero', fn (?string $currency = null) => new Money(0, new Currency($currency ?? 'GBP')));

$money = Money::zero();
```

### Mixins

Along with Macros, Mixins are also supported. This allows merging another classes methods into the Money or Currency class.

Define the mixin class:

```php
use Akaunting\Money\Money;

class CustomMoney
{
public function absolute(): Money
{
return $this->isPositive() ? $this : $this->multiply(-1);
}

public static function zero(?string $currency = null): Money
{
return new Money(0, new Currency($currency ?? 'GBP'));
}
}
```

Register the mixin, by passing an instance of the class:

```php
Money::mixin(new CustomMoney);
```

The methods from the custom class will be available:

```php
$money = Money::USD(1000)->multiply(-1);
$absolute = $money->absolute();

// Static methods via mixins are supported too:
$money = Money::zero();
```

## Changelog

Please see [Releases](../../releases) for more information on what has changed recently.
Expand Down
8 changes: 7 additions & 1 deletion src/Currency.php
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,9 @@
*/
class Currency implements Arrayable, Castable, Jsonable, JsonSerializable, Renderable
{
use Macroable;
use Macroable {
__callStatic as protected macroableCallStatic;
}

protected string $currency;

Expand Down Expand Up @@ -235,6 +237,10 @@ public function __construct(string $currency)

public static function __callStatic(string $method, array $arguments): Currency
{
if (static::hasMacro($method)) {
return static::macroableCallStatic($method, $arguments);
}

return new self($method);
}

Expand Down
8 changes: 7 additions & 1 deletion src/Money.php
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,9 @@
*/
class Money implements Arrayable, Castable, Jsonable, JsonSerializable, Renderable
{
use Macroable;
use Macroable {
__callStatic as protected macroableCallStatic;
}

const ROUND_HALF_UP = PHP_ROUND_HALF_UP;

Expand Down Expand Up @@ -283,6 +285,10 @@ protected function convertAmount(int|float $amount, bool $convert = false): int|

public static function __callStatic(string $method, array $arguments): Money
{
if (static::hasMacro($method)) {
return static::macroableCallStatic($method, $arguments);
}

$convert = isset($arguments[1]) && is_bool($arguments[1]) && $arguments[1];

return new self($arguments[0], new Currency($method), $convert);
Expand Down
7 changes: 7 additions & 0 deletions tests/CurrencyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,11 @@ public function testResetCurrencies()
$this->assertEmpty(Currency::getCurrencies());
Currency::setCurrencies($currencies);
}

public function testStaticMacro()
{
Currency::macro('testMacro', fn () => Currency::EUR());

$this->assertEquals(Currency::EUR(), Currency::testMacro());
}
}
7 changes: 7 additions & 0 deletions tests/MoneyTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -411,4 +411,11 @@ public function testMakingMutable()
$this->assertTrue($money->isImmutable());
$this->assertFalse($money->mutable()->isImmutable());
}

public function testStaticMacro()
{
Money::macro('testMacro', fn () => Money::USD(1099));

$this->assertEquals(Money::USD(1099), Money::testMacro());
}
}
Loading