From 5baaae7a7ad726eca8c2ffa3d09692b9494f72c4 Mon Sep 17 00:00:00 2001 From: Austin Drummond Date: Thu, 17 Aug 2023 10:10:37 -0400 Subject: [PATCH] Serializer Config (#136) * added money serializer * added a default serializer * fix return types * fix style * added tests for serializer * style ci * style * fix typos --- config/config.php | 1 + .../CurrencySymbolMoneyFormatter.php | 2 +- src/Money.php | 17 ++- src/MoneySerializer.php | 11 ++ src/MoneySerializerTrait.php | 67 ++++++++ src/Serializer/ArrayMoneySerializer.php | 24 +++ src/Serializer/DecimalMoneySerializer.php | 20 +++ src/Serializer/IntegerMoneySerializer.php | 20 +++ src/Serializer/StringMoneySerializer.php | 20 +++ tests/MoneyFormatterSerializerTest.php | 143 ++++++++++++++++++ 10 files changed, 319 insertions(+), 6 deletions(-) create mode 100644 src/MoneySerializer.php create mode 100644 src/MoneySerializerTrait.php create mode 100644 src/Serializer/ArrayMoneySerializer.php create mode 100644 src/Serializer/DecimalMoneySerializer.php create mode 100644 src/Serializer/IntegerMoneySerializer.php create mode 100644 src/Serializer/StringMoneySerializer.php create mode 100644 tests/MoneyFormatterSerializerTest.php diff --git a/config/config.php b/config/config.php index 04ce3d6..ad92a92 100644 --- a/config/config.php +++ b/config/config.php @@ -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', diff --git a/src/Formatters/CurrencySymbolMoneyFormatter.php b/src/Formatters/CurrencySymbolMoneyFormatter.php index f2a1dc9..56e7b61 100644 --- a/src/Formatters/CurrencySymbolMoneyFormatter.php +++ b/src/Formatters/CurrencySymbolMoneyFormatter.php @@ -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 diff --git a/src/Money.php b/src/Money.php index 091db1f..8afddce 100644 --- a/src/Money.php +++ b/src/Money.php @@ -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; @@ -84,6 +85,16 @@ public function getMoney() return $this->money; } + /** + * Get attributes. + * + * @return array + */ + public function getAttributes() + { + return $this->attributes; + } + /** * Divide. * @@ -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(); } /** diff --git a/src/MoneySerializer.php b/src/MoneySerializer.php new file mode 100644 index 0000000..4b4f7a8 --- /dev/null +++ b/src/MoneySerializer.php @@ -0,0 +1,11 @@ +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); + } +} diff --git a/src/Serializer/ArrayMoneySerializer.php b/src/Serializer/ArrayMoneySerializer.php new file mode 100644 index 0000000..87f326e --- /dev/null +++ b/src/Serializer/ArrayMoneySerializer.php @@ -0,0 +1,24 @@ +getAttributes(), + $money->getMoney()->jsonSerialize(), + ['formatted' => $money->render()] + ); + } +} diff --git a/src/Serializer/DecimalMoneySerializer.php b/src/Serializer/DecimalMoneySerializer.php new file mode 100644 index 0000000..09ed163 --- /dev/null +++ b/src/Serializer/DecimalMoneySerializer.php @@ -0,0 +1,20 @@ +formatByDecimal(); + } +} diff --git a/src/Serializer/IntegerMoneySerializer.php b/src/Serializer/IntegerMoneySerializer.php new file mode 100644 index 0000000..61b98fd --- /dev/null +++ b/src/Serializer/IntegerMoneySerializer.php @@ -0,0 +1,20 @@ +getAmount(); + } +} diff --git a/src/Serializer/StringMoneySerializer.php b/src/Serializer/StringMoneySerializer.php new file mode 100644 index 0000000..16e6fb7 --- /dev/null +++ b/src/Serializer/StringMoneySerializer.php @@ -0,0 +1,20 @@ +formatByIntl(); + } +} diff --git a/tests/MoneyFormatterSerializerTest.php b/tests/MoneyFormatterSerializerTest.php new file mode 100644 index 0000000..2960147 --- /dev/null +++ b/tests/MoneyFormatterSerializerTest.php @@ -0,0 +1,143 @@ + '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())); + } +}