Skip to content

Commit

Permalink
feat(NumberFormatterFactory)
Browse files Browse the repository at this point in the history
  • Loading branch information
h4kuna committed Mar 17, 2024
1 parent 72b8bb4 commit cce11f7
Show file tree
Hide file tree
Showing 7 changed files with 263 additions and 9 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@
],
"require": {
"php": ">=8.0",
"ext-intl": "*",
"h4kuna/data-type": "^v3.0.5"
},
"require-dev": {
"ext-intl": "*",
"nette/utils": "^3.0 || ^4.0",
"nette/tester": "^2.4",
"phpstan/phpstan": "^1.8",
Expand Down
13 changes: 7 additions & 6 deletions src/Number/Formatters/IntlNumberFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use h4kuna\Format\Number\Formatter;
use h4kuna\Format\Utils\Space;
use NumberFormatter;

/**
* NumberFormatter default settings:
Expand All @@ -13,7 +14,7 @@
final class IntlNumberFormatter implements Formatter
{
public function __construct(
private \NumberFormatter $formatter,
private NumberFormatter $formatter,
public string $emptyValue = '',
public bool $zeroIsEmpty = false,
)
Expand All @@ -27,11 +28,11 @@ public function modify(
?bool $zeroIsEmpty = null,
): self
{
$that = clone $this;
$that->zeroIsEmpty = $zeroIsEmpty ?? $that->zeroIsEmpty;
$that->emptyValue = $emptyValue === null ? $this->emptyValue : Space::nbsp($emptyValue);

return $that;
return new static(
$this->formatter,
$emptyValue ?? $this->emptyValue,
$zeroIsEmpty ?? $this->zeroIsEmpty,
);
}


Expand Down
11 changes: 11 additions & 0 deletions src/Number/NativePhp/NumberFormatter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php declare(strict_types=1);

namespace h4kuna\Format\Number\NativePhp;

class NumberFormatter extends \NumberFormatter
{
public function format(float|int $num, int $type = 0): string
{
return (string) parent::format($num, $type);
}
}
64 changes: 64 additions & 0 deletions src/Number/NativePhp/NumberFormatterFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
<?php declare(strict_types=1);

namespace h4kuna\Format\Number\NativePhp;

use Locale;

final class NumberFormatterFactory
{
private string $locale;


public function __construct(?string $locale = null)
{
$this->locale = $locale ?? Locale::getDefault();
}


/**
* @template T of NumberFormatter
* @param int|class-string<T> $style
* @return T
*/
public function create(
?int $decimals = null,
?string $locale = null,
int|string $style = NumberFormatter::DECIMAL
): NumberFormatter
{
$locale ??= $this->locale;
$formatter = is_int($style)
? new NumberFormatter($locale, $style)
: new $style($locale);

if ($decimals !== null) {
$formatter->setAttribute(NumberFormatter::FRACTION_DIGITS, $decimals);
}

return $formatter;

Check failure on line 38 in src/Number/NativePhp/NumberFormatterFactory.php

View workflow job for this annotation

GitHub Actions / PHPStan

Method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create() should return T of h4kuna\Format\Number\NativePhp\NumberFormatter but returns h4kuna\Format\Number\NativePhp\NumberFormatter.
}


public function currency(?string $locale = null): NumberFormatter
{
return $this->create(null, $locale, NumberFormatter::CURRENCY);

Check failure on line 44 in src/Number/NativePhp/NumberFormatterFactory.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
}


public function ordinal(?string $locale = null): NumberFormatter
{
return $this->create(null, $locale, NumberFormatter::ORDINAL);

Check failure on line 50 in src/Number/NativePhp/NumberFormatterFactory.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
}


public function percent(?int $decimals = 0, ?string $locale = null): NumberFormatterPercent
{
return $this->create($decimals, $locale, NumberFormatterPercent::class);
}


public function spell(?string $locale = null): NumberFormatter
{
return $this->create(null, $locale, NumberFormatter::SPELLOUT);

Check failure on line 62 in src/Number/NativePhp/NumberFormatterFactory.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
}
}
20 changes: 20 additions & 0 deletions src/Number/NativePhp/NumberFormatterPercent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php declare(strict_types=1);

namespace h4kuna\Format\Number\NativePhp;

use h4kuna\Format\Utils\Percentage;

final class NumberFormatterPercent extends NumberFormatter
{
public function __construct(string $locale)
{
parent::__construct($locale, self::PERCENT);
}


public function format(float|int $num, int $type = 0): string
{
return parent::format(Percentage::smallRatio((float) $num), $type);
}

}
11 changes: 9 additions & 2 deletions tests/src/Number/Formatters/IntlNumberFormatterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace h4kuna\Format\Tests\Number\Formatters;

use h4kuna\Format\Number\Formatters\IntlNumberFormatter;
use h4kuna\Format\Number\NativePhp\NumberFormatterFactory;
use h4kuna\Format\Tests\TestCase;
use h4kuna\Format\Utils\Space;
use NumberFormatter;
Expand All @@ -23,7 +24,7 @@ final class IntlNumberFormatterTest extends TestCase
*/
public function testFormat(array $parameters, string $expected, $number): void
{
$numberFormatter = new NumberFormatter('cs_CZ', NumberFormatter::DECIMAL);
$numberFormatter = self::createNumberFormatter();
$numberFormat = new IntlNumberFormatter($numberFormatter, ...$parameters);
Assert::same(Space::nbsp($expected), $numberFormat->format($number));
}
Expand All @@ -36,12 +37,18 @@ public function testFormat(array $parameters, string $expected, $number): void
*/
public function testModify(array $parameters, string $expected, $number): void
{
$numberFormatter = new NumberFormatter('cs_CZ', NumberFormatter::DECIMAL);
$numberFormatter = self::createNumberFormatter();
$numberFormat = (new IntlNumberFormatter($numberFormatter))->modify(...$parameters);
Assert::same(Space::nbsp($expected), $numberFormat->format($number));
}


private static function createNumberFormatter(): NumberFormatter
{
return (new NumberFormatterFactory('cs_CZ'))->create();

Check failure on line 48 in tests/src/Number/Formatters/IntlNumberFormatterTest.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
}


/**
* @return array<mixed>
*/
Expand Down
151 changes: 151 additions & 0 deletions tests/src/Number/NativePhp/NumberFormatterFactoryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
<?php

declare(strict_types=1);

namespace h4kuna\Format\Tests\Number\NativePhp;

use Closure;
use h4kuna\Format\Number\NativePhp\NumberFormatterFactory;
use h4kuna\Format\Tests\TestCase;
use h4kuna\Format\Utils\Space;
use NumberFormatter;
use Tester\Assert;

require_once __DIR__ . '/../../../bootstrap.php';

final class NumberFormatterFactoryTest extends TestCase
{
/**
* @return array<string|int, array{0: Closure(static):void}>
*/
public function dataNumber(): array
{
return [
[
function (self $self) {
$self->assertNbsp(
self::factory()->create(),

Check failure on line 27 in tests/src/Number/NativePhp/NumberFormatterFactoryTest.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
'1 000,345',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->create(0),

Check failure on line 35 in tests/src/Number/NativePhp/NumberFormatterFactoryTest.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
'1 000',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->create(1),

Check failure on line 43 in tests/src/Number/NativePhp/NumberFormatterFactoryTest.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
'1 000,3',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->create(4),

Check failure on line 51 in tests/src/Number/NativePhp/NumberFormatterFactoryTest.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
'1 000,3450',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->create(2, 'en_GB'),

Check failure on line 59 in tests/src/Number/NativePhp/NumberFormatterFactoryTest.php

View workflow job for this annotation

GitHub Actions / PHPStan

Unable to resolve the template type T in call to method h4kuna\Format\Number\NativePhp\NumberFormatterFactory::create()
'1,000.34',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->currency('en_GB'),
'£1,000.34',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->currency(),
'1 000,34 Kč',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->ordinal(),
'1 000.',
);
},
],
[
function (self $self) {
$self->assertNumber(
self::factory()->spell(),
'jedna tisíc čárka tři čtyři pět',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->percent(),
'1 000 %',
);
},
],
[
function (self $self) {
$self->assertNbsp(
self::factory()->percent(1),
'1 000,3 %',
);
},
],
];
}


/**
* @param Closure(static):void $assert
* @dataProvider dataNumber
*/
public function testNumber(Closure $assert): void
{
$assert($this);
}


public function assertNbsp(
NumberFormatter $formatter,
string $expected,
): void
{
Assert::same(Space::nbsp($expected), $formatter->format(1000.345));
}


public function assertNumber(
NumberFormatter $formatter,
string $expected,
): void
{
Assert::same($expected, $formatter->format(1000.345));
}


private static function factory(): NumberFormatterFactory
{
return new NumberFormatterFactory('cs_CZ');
}
}

(new NumberFormatterFactoryTest())->run();

0 comments on commit cce11f7

Please sign in to comment.