Skip to content

Commit

Permalink
Merge pull request #61 from aidan-casey/add-casting
Browse files Browse the repository at this point in the history
Adds casting to the package.
  • Loading branch information
denisdulici committed Apr 19, 2022
2 parents eaa684e + 7f1c85e commit 4481e7f
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 3 deletions.
4 changes: 3 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,14 @@
],
"require":{
"php":">=8.0",
"illuminate/contracts": ">=8.0",
"illuminate/support":">=8.0",
"illuminate/view":">=8.0"
},
"require-dev":{
"mockery/mockery":">=1.4",
"phpunit/phpunit":">=9.0"
"phpunit/phpunit":">=9.0",
"illuminate/database": "^9.8"
},
"autoload":{
"psr-4":{
Expand Down
28 changes: 28 additions & 0 deletions src/Casts/CurrencyCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace Akaunting\Money\Casts;

use Akaunting\Money\Currency;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use UnexpectedValueException;

class CurrencyCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes): Currency
{
if (! is_string($value)) {
throw new UnexpectedValueException;
}

return new Currency($value);
}

public function set($model, string $key, $value, array $attributes): string
{
if (! $value instanceof Currency) {
throw new UnexpectedValueException;
}

return $value->getCurrency();
}
}
41 changes: 41 additions & 0 deletions src/Casts/MoneyCast.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php

namespace Akaunting\Money\Casts;

use Akaunting\Money\Currency;
use Akaunting\Money\Money;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use UnexpectedValueException;

class MoneyCast implements CastsAttributes
{
public function get($model, string $key, $value, array $attributes): Money
{
if (! is_string($value)) {
throw new UnexpectedValueException;
}

$value = json_decode($value, true);

if (! $value || ! isset($value['amount']) || ! isset($value['currency'])) {
throw new UnexpectedValueException;
}

return new Money(
$value['amount'],
new Currency($value['currency'])
);
}

public function set($model, string $key, $value, array $attributes): string
{
if (! $value instanceof Money) {
throw new UnexpectedValueException;
}

return json_encode([
'amount' => $value->getAmount(),
'currency' => $value->getCurrency()->getCurrency(),
]);
}
}
17 changes: 16 additions & 1 deletion src/Currency.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

namespace Akaunting\Money;

use Akaunting\Money\Casts\CurrencyCast;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Renderable;
Expand Down Expand Up @@ -176,7 +179,7 @@
* @method static Currency ZMW()
* @method static Currency ZWL()
*/
class Currency implements Arrayable, Jsonable, JsonSerializable, Renderable
class Currency implements Arrayable, Castable, Jsonable, JsonSerializable, Renderable
{
/**
* @var string
Expand Down Expand Up @@ -275,6 +278,18 @@ public static function __callStatic($method, array $arguments)
return new static($method, $arguments);
}

/**
* castUsing
*
* @param array $arguments
*
* @return class-string<CastsAttributes>
*/
public static function castUsing(array $arguments): string
{
return CurrencyCast::class;
}

/**
* setCurrencies.
*
Expand Down
17 changes: 16 additions & 1 deletion src/Money.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@

namespace Akaunting\Money;

use Akaunting\Money\Casts\MoneyCast;
use BadFunctionCallException;
use Closure;
use Illuminate\Contracts\Database\Eloquent\Castable;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Contracts\Support\Jsonable;
use Illuminate\Contracts\Support\Renderable;
Expand Down Expand Up @@ -180,7 +183,7 @@
* @method static Money ZMW(mixed $amount, bool $convert = false)
* @method static Money ZWL(mixed $amount, bool $convert = false)
*/
class Money implements Arrayable, Jsonable, JsonSerializable, Renderable
class Money implements Arrayable, Castable, Jsonable, JsonSerializable, Renderable
{
const ROUND_HALF_UP = PHP_ROUND_HALF_UP;
const ROUND_HALF_DOWN = PHP_ROUND_HALF_DOWN;
Expand Down Expand Up @@ -329,6 +332,18 @@ public static function __callStatic($method, array $arguments)
return new static($arguments[0], new Currency($method), $convert);
}

/**
* castUsing
*
* @param array $arguments
*
* @return class-string<CastsAttributes>
*/
public static function castUsing(array $arguments): string
{
return MoneyCast::class;
}

/**
* getLocale.
*
Expand Down
45 changes: 45 additions & 0 deletions tests/Casts/CurrencyCastTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

use Akaunting\Money\Casts\CurrencyCast;
use Akaunting\Money\Currency;
use Illuminate\Database\Eloquent\Model;
use PHPUnit\Framework\TestCase;

class CurrencyCastTest extends TestCase
{
public function testItWillNotGetCurrencyFromNonStrings()
{
$this->expectException(UnexpectedValueException::class);

$model = $this->getMockBuilder(Model::class)->getMock();

(new CurrencyCast)->get($model, 'currency', 1, []);
}

public function testItWillNotSetCurrencyFromNonCurrencies()
{
$this->expectException(UnexpectedValueException::class);

$model = $this->getMockBuilder(Model::class)->getMock();

(new CurrencyCast)->set($model, 'currency', 'USD', []);
}

public function testItGetsCurrencyFromString()
{
$model = $this->getMockBuilder(Model::class)->getMock();

$value = (new CurrencyCast)->get($model, 'currency', 'USD', []);

$this->assertEquals(Currency::USD(), $value);
}

public function testItSetsCurrencyAsString()
{
$mock = $this->getMockBuilder(Model::class)->getMock();

$value = (new CurrencyCast)->set($mock, 'currency', Currency::USD(), []);

$this->assertSame('USD', $value);
}
}
54 changes: 54 additions & 0 deletions tests/Casts/MoneyCastTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

use Akaunting\Money\Casts\MoneyCast;
use Akaunting\Money\Currency;
use Akaunting\Money\Money;
use Illuminate\Database\Eloquent\Model;
use PHPUnit\Framework\TestCase;

class MoneyCastTest extends TestCase
{
public function testItWillNotGetMoneyFromNonJson()
{
$this->expectException(UnexpectedValueException::class);

$model = $this->getMockBuilder(Model::class)->getMock();

(new MoneyCast)->get($model, 'money', 'testing', []);
}

public function testItWillNotGetMoneyFromIllFormedJson()
{
$this->expectException(UnexpectedValueException::class);

$model = $this->getMockBuilder(Model::class)->getMock();

(new MoneyCast)->get($model, 'money', '{"key":"value"}', []);
}

public function testItGetsMoneyFromJson()
{
$model = $this->getMockBuilder(Model::class)->getMock();
$json = '{"amount":1000,"currency":"USD"}';

$value = (new MoneyCast)->get($model, 'money', $json, []);

$this->assertEquals(
new Money('1000', new Currency('USD')),
$value
);
}

public function testItSetsMoneyAsJson()
{
$model = $this->getMockBuilder(Model::class)->getMock();
$money = new Money('1200', Currency::USD());

$value = (new MoneyCast)->set($model, 'money', $money, []);

$this->assertSame(
'{"amount":1200,"currency":"USD"}',
$value
);
}
}
6 changes: 6 additions & 0 deletions tests/CurrencyTest.php
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
<?php

use Akaunting\Money\Casts\CurrencyCast;
use Akaunting\Money\Currency;
use PHPUnit\Framework\TestCase;

class CurrencyTest extends TestCase
{
public function testCastUsing()
{
$this->assertSame(CurrencyCast::class, Currency::castUsing([]));
}

public function testFactoryMethods()
{
$this->assertEquals(Currency::USD(), new Currency('USD'));
Expand Down
6 changes: 6 additions & 0 deletions tests/MoneyTest.php
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
<?php

use Akaunting\Money\Casts\MoneyCast;
use Akaunting\Money\Currency;
use Akaunting\Money\Money;
use PHPUnit\Framework\TestCase;

class MoneyTest extends TestCase
{
public function testCastUsing()
{
$this->assertSame(MoneyCast::class, Money::castUsing([]));
}

public function testFactoryMethods()
{
$this->assertEquals(Money::USD(25), Money::USD(10)->add(Money::USD(15)));
Expand Down

0 comments on commit 4481e7f

Please sign in to comment.