Skip to content

Commit

Permalink
Serializer Config (#136)
Browse files Browse the repository at this point in the history
* added money serializer

* added a default serializer

* fix return types

* fix style

* added tests for serializer

* style ci

* style

* fix typos
  • Loading branch information
adrum authored Aug 17, 2023
1 parent ca76245 commit 5baaae7
Show file tree
Hide file tree
Showing 10 changed files with 319 additions and 6 deletions.
1 change: 1 addition & 0 deletions config/config.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
'locale' => config('app.locale', 'en_US'),
'defaultCurrency' => config('app.currency', 'USD'),
'defaultFormatter' => null,
'defaultSerializer' => null,
'isoCurrenciesPath' => __DIR__.'/../vendor/moneyphp/money/resources/currency.php',
'currencies' => [
'iso' => 'all',
Expand Down
2 changes: 1 addition & 1 deletion src/Formatters/CurrencySymbolMoneyFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public function __construct($right = false, $locale = null, Currencies $currenci
/**
* Formats a Money object as string.
*
* @param \Money\Money $moeny
* @param \Money\Money $money
* @return string
*/
public function format(\Money\Money $money): string
Expand Down
17 changes: 12 additions & 5 deletions src/Money.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ class Money implements Arrayable, Jsonable, JsonSerializable, Renderable
MoneyFactory::__callStatic as factoryCallStatic;
}
use MoneyFormatterTrait;
use MoneySerializerTrait;
use MoneyParserTrait;
use Macroable {
Macroable::__call as macroCall;
Expand Down Expand Up @@ -84,6 +85,16 @@ public function getMoney()
return $this->money;
}

/**
* Get attributes.
*
* @return array
*/
public function getAttributes()
{
return $this->attributes;
}

/**
* Divide.
*
Expand Down Expand Up @@ -146,11 +157,7 @@ public function attributes(array $attributes = [])
#[\ReturnTypeWillChange]
public function jsonSerialize()
{
return array_merge(
$this->attributes,
$this->money->jsonSerialize(),
['formatted' => $this->render()]
);
return $this->serialize();
}

/**
Expand Down
11 changes: 11 additions & 0 deletions src/MoneySerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

namespace Cknow\Money;

/**
* Serializes Money objects.
*/
interface MoneySerializer
{
public function serialize(Money $money): mixed;
}
67 changes: 67 additions & 0 deletions src/MoneySerializerTrait.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

namespace Cknow\Money;

use Cknow\Money\Serializer\ArrayMoneySerializer;
use InvalidArgumentException;

trait MoneySerializerTrait
{
/**
* Serialize.
*
* @param string|null $locale
* @param \Money\Currencies|null $currencies
* @param int $style
* @return string
*
* @throws \InvalidArgumentException
*/
public function serialize()
{
$defaultSerializer = config('money.defaultSerializer');

if (is_null($defaultSerializer)) {
return $this->serializeByArray();
}

$serializer = null;

if (is_string($defaultSerializer)) {
$serializer = app($defaultSerializer);
}

if (is_array($defaultSerializer) && count($defaultSerializer) === 2) {
$serializer = app($defaultSerializer[0], $defaultSerializer[1]);
}

if ($serializer instanceof MoneySerializer) {
return $this->serializeBySerializer($serializer);
}

throw new InvalidArgumentException(sprintf('Invalid default serializer %s', json_encode($defaultSerializer)));
}

/**
* Serialize by array.
*
* @return mixed
*/
public function serializeByArray()
{
$serializer = new ArrayMoneySerializer();

return $this->serializeBySerializer($serializer);
}

/**
* Serialize by serializer.
*
* @param \Cknow\Money\MoneySerializer $serializer
* @return string
*/
public function serializeBySerializer(MoneySerializer $serializer)
{
return $serializer->serialize($this);
}
}
24 changes: 24 additions & 0 deletions src/Serializer/ArrayMoneySerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

namespace Cknow\Money\Serializer;

use Cknow\Money\Money;
use Cknow\Money\MoneySerializer;

class ArrayMoneySerializer implements MoneySerializer
{
/**
* Formats a Money object as string.
*
* @param \Money\Money $money
* @return mixed
*/
public function serialize(Money $money): mixed
{
return array_merge(
$money->getAttributes(),
$money->getMoney()->jsonSerialize(),
['formatted' => $money->render()]
);
}
}
20 changes: 20 additions & 0 deletions src/Serializer/DecimalMoneySerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Cknow\Money\Serializer;

use Cknow\Money\Money;
use Cknow\Money\MoneySerializer;

class DecimalMoneySerializer implements MoneySerializer
{
/**
* Formats a Money object as string.
*
* @param \Money\Money $money
* @return mixed
*/
public function serialize(Money $money): mixed
{
return $money->formatByDecimal();
}
}
20 changes: 20 additions & 0 deletions src/Serializer/IntegerMoneySerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Cknow\Money\Serializer;

use Cknow\Money\Money;
use Cknow\Money\MoneySerializer;

class IntegerMoneySerializer implements MoneySerializer
{
/**
* Formats a Money object as string.
*
* @param \Money\Money $money
* @return mixed
*/
public function serialize(Money $money): mixed
{
return (int) $money->getAmount();
}
}
20 changes: 20 additions & 0 deletions src/Serializer/StringMoneySerializer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php

namespace Cknow\Money\Serializer;

use Cknow\Money\Money;
use Cknow\Money\MoneySerializer;

class StringMoneySerializer implements MoneySerializer
{
/**
* Formats a Money object as string.
*
* @param \Money\Money $money
* @return mixed
*/
public function serialize(Money $money): mixed
{
return (string) $money->formatByIntl();
}
}
143 changes: 143 additions & 0 deletions tests/MoneyFormatterSerializerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
<?php

namespace Cknow\Money\Tests;

use Cknow\Money\Money;
use Cknow\Money\Serializer\ArrayMoneySerializer;
use Cknow\Money\Serializer\DecimalMoneySerializer;
use Cknow\Money\Serializer\IntegerMoneySerializer;
use Cknow\Money\Serializer\StringMoneySerializer;
use InvalidArgumentException;

class MoneySerializerTraitTest extends TestCase
{
public function testSerialize()
{
static::assertEquals([
'amount' => '100',
'currency' => 'USD',
'formatted' => '$1.00',
], Money::USD(100)->serialize());
static::assertEquals([
'amount' => '100',
'currency' => 'EUR',
'formatted' => '€1.00',
], Money::EUR(100)->serialize());
static::assertEquals([
'amount' => '199',
'currency' => 'EUR',
'formatted' => '€1.99',
], Money::EUR(199)->serialize());
}

public function testDefaultSerializer()
{
config(['money.defaultSerializer' => null]);
static::assertEquals([
'amount' => '100',
'currency' => 'USD',
'formatted' => '$1.00',
], Money::USD(100)->serialize());

config(['money.defaultSerializer' => ArrayMoneySerializer::class]);
static::assertEquals([
'amount' => '100',
'currency' => 'USD',
'formatted' => '$1.00',
], Money::USD(100)->serialize());

config(['money.defaultSerializer' => DecimalMoneySerializer::class]);
static::assertEquals('1.00', Money::USD(100)->serialize());

config(['money.defaultSerializer' => IntegerMoneySerializer::class]);
static::assertEquals(100, Money::USD(100)->serialize());

config(['money.defaultSerializer' => StringMoneySerializer::class]);
static::assertEquals('$1.00', Money::USD(100)->serialize());

config(['money.defaultSerializer' => null]);
static::assertEquals([
'amount' => '100',
'currency' => 'EUR',
'formatted' => '€1.00',
], Money::EUR(100)->serialize());

config(['money.defaultSerializer' => ArrayMoneySerializer::class]);
static::assertEquals([
'amount' => '100',
'currency' => 'EUR',
'formatted' => '€1.00',
], Money::EUR(100)->serialize());

config(['money.defaultSerializer' => [DecimalMoneySerializer::class, []]]);
static::assertEquals('1.00', Money::EUR(100)->serialize());

config(['money.defaultSerializer' => [IntegerMoneySerializer::class, []]]);
static::assertEquals(100, Money::EUR(100)->serialize());

config(['money.defaultSerializer' => [StringMoneySerializer::class, []]]);
static::assertEquals('€1.00', Money::EUR(100)->serialize());
}

public function testInvalidDefaultSerializer()
{
$defaultSerializer = [BitcoinMoneySerializer::class];

$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid default serializer '.json_encode($defaultSerializer));

config(['money.defaultSerializer' => $defaultSerializer]);
static::assertEquals('$1.00', Money::USD(100)->serialize());
}

public function testSerializeByArray()
{
static::assertEquals([
'amount' => '100',
'currency' => 'USD',
'formatted' => '$1.00',
], Money::USD(100)->serializeByArray());

static::assertEquals([
'amount' => '100',
'currency' => 'EUR',
'formatted' => '€1.00',
], Money::EUR(100)->serializeByArray());
}

public function testSerializeBySerializerWithArray()
{
static::assertEquals([
'amount' => '100',
'currency' => 'USD',
'formatted' => '$1.00',
], Money::USD(100)->serializeBySerializer(new ArrayMoneySerializer()));

static::assertEquals([
'amount' => '100',
'currency' => 'EUR',
'formatted' => '€1.00',
], Money::EUR(100)->serializeBySerializer(new ArrayMoneySerializer()));
}

public function testSerializeByDecimal()
{
static::assertEquals('1.00', Money::USD(100)->serializeBySerializer(new DecimalMoneySerializer()));

static::assertEquals('1.00', Money::EUR(100)->serializeBySerializer(new DecimalMoneySerializer()));
}

public function testSerializeByInteger()
{
static::assertEquals(100, Money::USD(100)->serializeBySerializer(new IntegerMoneySerializer()));

static::assertEquals(100, Money::EUR(100)->serializeBySerializer(new IntegerMoneySerializer()));
}

public function testSerializeByString()
{
static::assertEquals('$1.00', Money::USD(100)->serializeBySerializer(new StringMoneySerializer()));

static::assertEquals('€1.00', Money::EUR(100)->serializeBySerializer(new StringMoneySerializer()));
}
}

0 comments on commit 5baaae7

Please sign in to comment.