From 45570f97e0f1d081851f810828dd9f125fe25272 Mon Sep 17 00:00:00 2001 From: Peter Elmered Date: Thu, 22 Feb 2024 04:59:47 +0100 Subject: [PATCH] Refactor/Improvements --- config/filament-money-field.php | 22 +++++++++++ src/Forms/Components/MoneyInput.php | 49 ++++++++++++++++--------- src/Infolists/Components/MoneyEntry.php | 2 +- src/MoneyFormatter.php | 34 +++++------------ src/Tables/Columns/MoneyColumn.php | 2 +- src/hasMoneyAttributes.php | 7 ---- 6 files changed, 66 insertions(+), 50 deletions(-) diff --git a/config/filament-money-field.php b/config/filament-money-field.php index 6386e1b..8486c96 100644 --- a/config/filament-money-field.php +++ b/config/filament-money-field.php @@ -33,4 +33,26 @@ | */ 'use_input_mask' => env('MONEY_USE_INPUT_MASK', false), + + /* + |--------------------------------------------------------------------------- + | International currency symbol + |--------------------------------------------------------------------------- + | + | Use international currency symbols. For example: USD, EUR, SEK instead of $, €, kr etc. + | + */ + 'intl_currency_symbol' => env('MONEY_INTL_CURRENCY_SYMBOL', false), + + + /* + |--------------------------------------------------------------------------- + | Currency symbol placement + |--------------------------------------------------------------------------- + | + | Where the dunit should be on form fields. Options are 'before' (prefix), 'after' (suffix) or 'none'. + | + */ + 'form_currency_symbol_placement' => env('MONEY_UNIT_PLACEMENT', 'before'), + ]; diff --git a/src/Forms/Components/MoneyInput.php b/src/Forms/Components/MoneyInput.php index 0fa18b1..15c00a5 100644 --- a/src/Forms/Components/MoneyInput.php +++ b/src/Forms/Components/MoneyInput.php @@ -4,6 +4,7 @@ use Filament\Forms\Components\TextInput; use Filament\Support\RawJs; +use Illuminate\Support\Facades\Config; use Pelmered\FilamentMoneyField\hasMoneyAttributes; use Pelmered\FilamentMoneyField\MoneyFormatter; @@ -15,8 +16,10 @@ protected function setUp(): void { parent::setUp(); + $this->prepare($this); + $this->formatStateUsing(function (MoneyInput $component, $state): ?string { - + $this->prepare($component); $currency = $component->getCurrency(); @@ -34,7 +37,7 @@ protected function setUp(): void $this->dehydrateStateUsing(function (MoneyInput $component, $state): string { - $currency = $component->getCurrency()->getCode(); + $currency = $component->getCurrency(); $state = MoneyFormatter::parseDecimal($state, $currency, $component->getLocale()); $this->prepare($component); @@ -46,7 +49,13 @@ protected function setUp(): void protected function prepare(MoneyInput $component): void { $formattingRules = MoneyFormatter::getFormattingRules($component->getLocale()); - $this->prefix($formattingRules->currencySymbol); + $symbolPlacement = Config::get('filament-money-field.form_currency_symbol_placement', 'before'); + + if ($symbolPlacement === 'before') { + $this->prefix($formattingRules->currencySymbol); + } else { + $this->suffix($formattingRules->currencySymbol); + } if (config('filament-money-field.use_input_mask')) { $this->mask(RawJs::make('$money($input, \'' . $formattingRules->decimalSeparator . '\', \'' . $formattingRules->groupingSeparator . '\', ' . $formattingRules->fractionDigits . ')')); @@ -58,14 +67,17 @@ public function minValue(mixed $min): static $this->rule(static function (MoneyInput $component, mixed $state) use ($min) { return function (string $attribute, mixed $value, \Closure $fail) use ($component, $state, $min) { - $value = MoneyFormatter::parseDecimal( - $state, - $component->getCurrency()->getCode(), - $component->getLocale() + $currencyCode = $component->getCurrency(); + $locale = $component->getLocale(); + + $minorValue = MoneyFormatter::parseDecimal( + $state, + $currencyCode, + $locale ); - if ($value < $min) { - $fail('The :attribute must be greater than or equal to ' . $min . '.'); + if ($minorValue < $min) { + $fail('The :attribute must be greater than or equal to ' . MoneyFormatter::formatAsDecimal($min, $currencyCode, $locale) . '.'); } }; }); @@ -75,17 +87,20 @@ public function minValue(mixed $min): static public function maxValue(mixed $max): static { - $this->rule(static function (MoneyInput $component, mixed $state) use ($max) { - return function (string $attribute, mixed $value, \Closure $fail) use ($component, $state, $max) { + $this->rule(static function (MoneyInput $component) use ($max) { + return function (string $attribute, mixed $value, \Closure $fail) use ($component, $max) { + + $currencyCode = $component->getCurrency(); + $locale = $component->getLocale(); - $value = MoneyFormatter::parseDecimal( - $state, - $component->getCurrency()->getCode(), - $component->getLocale() + $minorValue = MoneyFormatter::parseDecimal( + $value, + $currencyCode, + $locale ); - if ($value > $max) { - $fail('The :attribute must be less than or equal to ' . $max . '.'); + if ($minorValue > $max) { + $fail('The :attribute must be less than or equal to ' . MoneyFormatter::formatAsDecimal($max, $currencyCode, $locale) . '.'); } }; }); diff --git a/src/Infolists/Components/MoneyEntry.php b/src/Infolists/Components/MoneyEntry.php index adc65ff..6a13346 100644 --- a/src/Infolists/Components/MoneyEntry.php +++ b/src/Infolists/Components/MoneyEntry.php @@ -21,7 +21,7 @@ protected function setUp(): void $currency = $component->getCurrency(); $locale = $component->getLocale(); - return MoneyFormatter::format($state, $currency, $locale, $this->monetarySeparator); + return MoneyFormatter::format($state, $currency, $locale); }); } } diff --git a/src/MoneyFormatter.php b/src/MoneyFormatter.php index e13ec8c..95c9611 100644 --- a/src/MoneyFormatter.php +++ b/src/MoneyFormatter.php @@ -11,33 +11,25 @@ class MoneyFormatter { - public static function format($value, $currency, $locale, $monetarySeparator = null): string + public static function format(null|int|string $value, Currency $currency, string $locale, int $outputStyle = NumberFormatter::CURRENCY): string { if (is_null($value) || $value === '') { return ''; } - $numberFormatter = self::getNumberFormatter($locale, NumberFormatter::CURRENCY); + $numberFormatter = self::getNumberFormatter($locale, $outputStyle); $moneyFormatter = new IntlMoneyFormatter($numberFormatter, new ISOCurrencies()); $money = new Money($value, $currency); - return $moneyFormatter->format($money); + return $moneyFormatter->format($money); // outputs $1.000,00 } - public static function formatAsDecimal($value, $currency, $locale): string + public static function formatAsDecimal(null|int|string $value, Currency $currency, string $locale): string { - if (is_null($value) || $value === '') { - return ''; - } - - $numberFormatter = self::getNumberFormatter($locale, \NumberFormatter::DECIMAL); - $moneyFormatter = new IntlMoneyFormatter($numberFormatter, new ISOCurrencies()); - - $money = new Money($value, $currency); - return $moneyFormatter->format($money); // outputs 1.000,00 + return static::format($value, $currency, $locale, NumberFormatter::DECIMAL); // outputs 1.000,00 } - public static function parseDecimal($moneyString, $currency, $locale): string + public static function parseDecimal($moneyString, Currency $currency, string $locale): string { if (is_null($moneyString) || $moneyString === '') { return ''; @@ -47,17 +39,16 @@ public static function parseDecimal($moneyString, $currency, $locale): string $numberFormatter = self::getNumberFormatter($locale, NumberFormatter::DECIMAL); $moneyParser = new IntlLocalizedDecimalParser($numberFormatter, $currencies); - $money = $moneyParser->parse($moneyString, new Currency($currency)); - - return $money->getAmount(); + return $moneyParser->parse($moneyString, $currency)->getAmount(); } public static function getFormattingRules($locale): MoneyFormattingRules { + $config = config('filament-money-field'); $numberFormatter = new NumberFormatter($locale, NumberFormatter::CURRENCY); return new MoneyFormattingRules( - currencySymbol: $numberFormatter->getSymbol(NumberFormatter::CURRENCY_SYMBOL), + currencySymbol: $numberFormatter->getSymbol($config['intl_currency_symbol'] ? NumberFormatter::INTL_CURRENCY_SYMBOL : NumberFormatter::CURRENCY_SYMBOL), fractionDigits: $numberFormatter->getAttribute(NumberFormatter::FRACTION_DIGITS), decimalSeparator: $numberFormatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL), groupingSeparator: $numberFormatter->getSymbol(NumberFormatter::GROUPING_SEPARATOR_SYMBOL), @@ -66,12 +57,7 @@ public static function getFormattingRules($locale): MoneyFormattingRules public static function decimalToMoneyString($moneyString, $locale): string { - $formattingRules = self::getFormattingRules($locale); - $moneyString = (string)$moneyString; - - $moneyString = str_replace(',', '.', (string)$moneyString); - - return $moneyString; + return str_replace(',', '.', (string)$moneyString); } private static function getNumberFormatter($locale, int $style): NumberFormatter diff --git a/src/Tables/Columns/MoneyColumn.php b/src/Tables/Columns/MoneyColumn.php index 50a8c04..e9ffe06 100644 --- a/src/Tables/Columns/MoneyColumn.php +++ b/src/Tables/Columns/MoneyColumn.php @@ -21,7 +21,7 @@ protected function setUp(): void $currency = $column->getCurrency(); $locale = $column->getLocale(); - return MoneyFormatter::format($state, $currency, $locale, $this->monetarySeparator); + return MoneyFormatter::format($state, $currency, $locale); }); } diff --git a/src/hasMoneyAttributes.php b/src/hasMoneyAttributes.php index f3ff698..dd4cb26 100644 --- a/src/hasMoneyAttributes.php +++ b/src/hasMoneyAttributes.php @@ -40,11 +40,4 @@ public function locale(string|\Closure|null $locale = null): static return $this; } - - public function monetarySeparator(string|\Closure|null $monetarySeparator = null): static - { - $this->monetarySeparator = $monetarySeparator; - - return $this; - } }