Skip to content

Commit

Permalink
Merge pull request #88 from Luke-Shepp/feature/87-static-macros
Browse files Browse the repository at this point in the history
#87 - Allow static macros
  • Loading branch information
denisdulici authored Jul 21, 2023
2 parents dc6dd20 + b43e60f commit e684359
Show file tree
Hide file tree
Showing 5 changed files with 98 additions and 2 deletions.
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());
}
}

0 comments on commit e684359

Please sign in to comment.