Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
allanmcarvalho committed Nov 20, 2023
1 parent b7ebf23 commit 7f94b05
Show file tree
Hide file tree
Showing 5 changed files with 178 additions and 1 deletion.
17 changes: 17 additions & 0 deletions config/numerable.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
<?php

// config for Numerable
return [

/*
|--------------------------------------------------------------------------
| Default Currency
|--------------------------------------------------------------------------
|
| This will be the default currency used when formatting a number to a
| currency. You can change this value to any currency code supported by the
| NumberFormatter class. Alternatively, you can set the currency when
| formatting a number by using the toCurrency() method.
*/
'default_currency' => env('NUMERABLE_DEFAULT_CURRENCY', 'USD'),
];
57 changes: 57 additions & 0 deletions src/Number.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@

namespace Numerable;

use Illuminate\Support\Collection;
use InvalidArgumentException;
use NumberFormatter;

class Number
{
protected static Collection $formatters;

/**
* Sum the given values.
*/
Expand Down Expand Up @@ -50,6 +53,37 @@ public static function from(Numerable|int|float|string|null $number): ?Numerable
return null;
}

/**
* Get and store a new NumberFormatter instance.
*/
public static function getIntlFormatter(
?string $locale,
int $style,
?int $places = null,
?int $precision = null,
?string $pattern = null,
): NumberFormatter {
$key = "$locale::$style::$places::$precision::$pattern";
if (empty(self::$formatters)) {
self::$formatters = new Collection();
}
return self::$formatters->getOrPut($key, function () use ($locale, $style, $places, $precision, $pattern) {
$formatter = new NumberFormatter($locale ?? config('app.locale', 'en'), $style);
if ($places !== null) {
$formatter->setAttribute(NumberFormatter::MIN_FRACTION_DIGITS, $places);
$formatter->setAttribute(NumberFormatter::MAX_FRACTION_DIGITS, $places);
}
if ($precision !== null) {
$formatter->setAttribute(NumberFormatter::MIN_SIGNIFICANT_DIGITS, $precision);
$formatter->setAttribute(NumberFormatter::MAX_SIGNIFICANT_DIGITS, $precision);
}
if ($pattern !== null) {
$formatter->setPattern($pattern);
}
return $formatter;
});
}

/**
* Multiply the given values.
*/
Expand Down Expand Up @@ -88,6 +122,29 @@ public static function sub(int|float $startValue = 0, int|float ...$values): flo
return $result;
}

/**
* Parse the given number to a currency.
*/
public static function toCurrency(
int|float $value,
string $currency = null,
string $locale = null,
bool $accounting = false,
bool $useIntlCode = false,
int $places = null,
int $precision = null,
): string {
$style = $accounting ? NumberFormatter::CURRENCY_ACCOUNTING : NumberFormatter::CURRENCY;
$numberFormatter = self::getIntlFormatter($locale, $style, $places, $precision);
if ($useIntlCode) {
$pattern = trim(str_replace('¤', '¤¤', $numberFormatter->getPattern()));
$numberFormatter = clone $numberFormatter;
$numberFormatter->setPattern($pattern);
}
$currency = $currency ?? config('numerable.default_currency', 'USD');
return $numberFormatter->formatCurrency($value, $currency);
}

/**
* Parse the given number to a float type.
*/
Expand Down
14 changes: 14 additions & 0 deletions src/Numerable.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,20 @@ public function sub(Numerable|int|float|string ...$values): static
return new static(Number::sub($this->number, ...$numbers));
}

/**
* Format the instance to a currency.
*/
public function toCurrency(
string $currency = null,
string $locale = null,
bool $accounting = false,
bool $useIntlCode = false,
int $places = null,
int $precision = null,
): string {
return Number::toCurrency($this->number, $currency, $locale, $accounting, $useIntlCode, $places, $precision);
}

/**
* Parse to a float instance.
*/
Expand Down
3 changes: 2 additions & 1 deletion src/NumerableServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ public function configurePackage(Package $package): void
* More info: https://github.com/spatie/laravel-package-tools
*/
$package
->name('numerable');
->name('numerable')
->hasConfigFile();
}
}
88 changes: 88 additions & 0 deletions tests/NumberCurrencyTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

use Numerable\Number;
use Numerable\Numerable;

it('can do a simple format', function () {
expect(Number::toCurrency(22.32))
->toBeString()
->toEqual('$22.32');
});

it('can do a simple format using helper', function () {
expect(num()->toCurrency(22.32))
->toBeString()
->toEqual('$22.32');
});

it('can format with default params', function () {
$number = num(new Numerable(12.59));
$formatted = $number->toCurrency();

expect($formatted)
->toBeString()
->toEqual('$12.59');
});

it('can format in other currency', function () {
$number = num(new Numerable(21.21));
$formatted = $number->toCurrency('BRL');

expect($formatted)
->toBeString()
->toEqual('R$21.21');
});

it('can format in other currency in other locale', function () {
$number = num(new Numerable(1_234.42));
$formatted = $number->toCurrency('BRL', 'pt_BR');

expect($formatted)
->toBeString()
->toEqual("R$\u{A0}1.234,42");
});

it('can format using intl code', function () {
$number = num(new Numerable(34.21));
$formatted = $number->toCurrency(useIntlCode: true);

expect($formatted)
->toBeString()
->toEqual("USD\u{A0}34.21");
});

it('can format without account', function () {
$number = num(new Numerable(-15.15));
$formatted = $number->toCurrency();

expect($formatted)
->toBeString()
->toEqual("-$15.15");
});

it('can format with account', function () {
$number = num(new Numerable(-15.15));
$formatted = $number->toCurrency(accounting: true);

expect($formatted)
->toBeString()
->toEqual("($15.15)");
});

it('can format with 4 places', function () {
$number = num(new Numerable(10.2222));
$formatted = $number->toCurrency(places: 4);

expect($formatted)
->toBeString()
->toEqual("$10.2222");
});

it('can format with 4 precision', function () {
$number = num(new Numerable(10.2222));
$formatted = $number->toCurrency(places: 4, precision: 4);

expect($formatted)
->toBeString()
->toEqual("$10.22");
});

0 comments on commit 7f94b05

Please sign in to comment.