RETROTEC-AG/OpenXE#18 Number parser implementieren
This commit is contained in:
parent
c258166bcb
commit
a64345976e
|
|
@ -1,5 +1,5 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/*
|
||||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
* SPDX-License-Identifier: AGPL-3.0-only
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
*/
|
*/
|
||||||
|
|
@ -16,7 +16,7 @@ use Xentral\Core\DependencyInjection\ServiceContainer;
|
||||||
/**
|
/**
|
||||||
* Factory for localization object.
|
* Factory for localization object.
|
||||||
*
|
*
|
||||||
* @see Localization
|
* @see Localization
|
||||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
*/
|
*/
|
||||||
final class Bootstrap
|
final class Bootstrap
|
||||||
|
|
@ -28,6 +28,7 @@ final class Bootstrap
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'Localization' => 'onInitLocalization',
|
'Localization' => 'onInitLocalization',
|
||||||
|
'FormatterService' => 'onInitFormatterService',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -111,7 +112,9 @@ final class Bootstrap
|
||||||
/** @var Database $db */
|
/** @var Database $db */
|
||||||
$db = $container->get('Database');
|
$db = $container->get('Database');
|
||||||
|
|
||||||
$config=[];
|
$config = [];
|
||||||
|
$firmaLang = null;
|
||||||
|
$firmaRegion = null;
|
||||||
// Get language from system settings and normalize to 3-letter-code and 2-letter-code
|
// Get language from system settings and normalize to 3-letter-code and 2-letter-code
|
||||||
if ($firmaLang = self::findLanguage(strval($app->erp->Firmendaten('preferredLanguage')))) {
|
if ($firmaLang = self::findLanguage(strval($app->erp->Firmendaten('preferredLanguage')))) {
|
||||||
$config[Localization::LANGUAGE_DEFAULT] = $firmaLang[Iso639\Key::ALPHA_3];
|
$config[Localization::LANGUAGE_DEFAULT] = $firmaLang[Iso639\Key::ALPHA_3];
|
||||||
|
|
@ -146,4 +149,14 @@ final class Bootstrap
|
||||||
// Create Localization object
|
// Create Localization object
|
||||||
return new Localization($request, $session, $usersettings, $config);
|
return new Localization($request, $session, $usersettings, $config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public static function onInitFormatterService(ServiceContainer $container): FormatterService
|
||||||
|
{
|
||||||
|
$localization = $container->get('Localization');
|
||||||
|
$locale = $localization->getLocale();
|
||||||
|
return new FormatterService($locale);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter;
|
||||||
|
|
||||||
|
use Vtiful\Kernel\Format;
|
||||||
|
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* AbstractFormatter.
|
||||||
|
*
|
||||||
|
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
*/
|
||||||
|
abstract class AbstractFormatter implements FormatterInterface
|
||||||
|
{
|
||||||
|
private string $locale;
|
||||||
|
private FormatterMode $strictness;
|
||||||
|
private mixed $parsedValue;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function __construct(string $locale, FormatterMode $strictness = FormatterMode::MODE_STRICT)
|
||||||
|
{
|
||||||
|
$this->locale = $locale;
|
||||||
|
$this->strictness = $strictness;
|
||||||
|
$this->init();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the formatter. Overload this instead of the constructor.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function init(): void
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the native PHP value in the formatter.
|
||||||
|
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
protected function setParsedValue($value): self
|
||||||
|
{
|
||||||
|
$this->parsedValue = $value;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the native PHP value in the formatter.
|
||||||
|
* The value must ALWAYS be of the requested type (or NULL or '' depending on the strictness).
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setPhpVal(mixed $input): self
|
||||||
|
{
|
||||||
|
if ($this->isStrictValidPhpVal($input)
|
||||||
|
|| $this->isEmptyValidPhpValue($input)
|
||||||
|
|| $this->isNullValidPhpValue($input)) {
|
||||||
|
$this->parsedValue = $input;
|
||||||
|
return $this;
|
||||||
|
} else {
|
||||||
|
throw new TypeErrorException(
|
||||||
|
"Value " . var_export($input, true) . " is not a valid type for " . get_class(
|
||||||
|
$this
|
||||||
|
) . " with strictness {$this->getStrictness()->name}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the native PHP value from the formatter.
|
||||||
|
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getPhpVal(): mixed
|
||||||
|
{
|
||||||
|
return $this->parsedValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the locale used for output formatting.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function getLocale(): string
|
||||||
|
{
|
||||||
|
return $this->locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the current strictness mode.
|
||||||
|
*
|
||||||
|
* @return FormatterMode
|
||||||
|
* @see FormatterMode
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public function getStrictness(): FormatterMode
|
||||||
|
{
|
||||||
|
return $this->strictness;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if $input conforms to the MODE_NULL strictness AND strictness is set.
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isNullValidPhpValue(mixed $input): bool
|
||||||
|
{
|
||||||
|
return ($this->getStrictness() == FormatterMode::MODE_NULL) && ($input === null);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if $input conforms to the MODE_EMPTY strictness AND strictness is set.
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
protected function isEmptyValidPhpValue(mixed $input): bool
|
||||||
|
{
|
||||||
|
return ($this->getStrictness() == FormatterMode::MODE_EMPTY) && is_string($input) && (trim($input) === '');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clean up input string.
|
||||||
|
*
|
||||||
|
* @param string $string
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected function sanitizeInputString(string $string): string
|
||||||
|
{
|
||||||
|
return trim($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,142 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter;
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Bootstrap;
|
||||||
|
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||||
|
|
||||||
|
class CurrencyFormatter extends FloatFormatter
|
||||||
|
{
|
||||||
|
private string $ccy;
|
||||||
|
private bool $showCcy = true;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected function init(): void
|
||||||
|
{
|
||||||
|
$this->parseType = \NumberFormatter::TYPE_CURRENCY;
|
||||||
|
$this->formatterStyle = \NumberFormatter::CURRENCY;
|
||||||
|
parent::init();
|
||||||
|
|
||||||
|
$parsedLocale = \Locale::parseLocale($this->getLocale());
|
||||||
|
$this->setCcy(
|
||||||
|
Bootstrap::findRegion($parsedLocale['region'])[\Xentral\Components\I18n\Iso3166\Key::CURRENCY_CODE] ?? ''
|
||||||
|
);
|
||||||
|
|
||||||
|
// Set text representation for currency, not the symbol
|
||||||
|
$this->getNumberFormatter()->setSymbol(\NumberFormatter::CURRENCY_SYMBOL, $this->getCcy());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the currency.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function getCcy(): string
|
||||||
|
{
|
||||||
|
return $this->ccy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the currency. Currency is also automatically set by locale, if class is
|
||||||
|
* instantiated.
|
||||||
|
*
|
||||||
|
* @param string $ccy
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setCcy(string $ccy): self
|
||||||
|
{
|
||||||
|
$this->ccy = $ccy;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't show currency in formatted output and don't expect currency in string to parse.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function hideCurrency(): self
|
||||||
|
{
|
||||||
|
$this->showCcy = false;
|
||||||
|
$this->parseType = \NumberFormatter::TYPE_DOUBLE;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show currency in formatted output and expect it in string to parse.
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function showCurrency(): self
|
||||||
|
{
|
||||||
|
$this->showCcy = true;
|
||||||
|
$this->parseType = \NumberFormatter::TYPE_CURRENCY;
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected function sanitizeInputString(string $string): string
|
||||||
|
{
|
||||||
|
return $this->showCcy
|
||||||
|
? trim($string)
|
||||||
|
: parent::sanitizeInputString($string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected function parse(string $input, ?\NumberFormatter $numberFormatter = null): false|float|int
|
||||||
|
{
|
||||||
|
if (!$this->showCcy) {
|
||||||
|
// If currency is not shown, create a new \NumberFormatter with style DECIMAL
|
||||||
|
$numberFormatter = new \NumberFormatter(
|
||||||
|
$this->getNumberFormatter()->getLocale(),
|
||||||
|
\NumberFormatter::DECIMAL,
|
||||||
|
$this->getNumberFormatter()->getPattern()
|
||||||
|
);
|
||||||
|
return parent::parse($input, $numberFormatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($numberFormatter === null) {
|
||||||
|
$numberFormatter = $this->getNumberFormatter();
|
||||||
|
}
|
||||||
|
return $numberFormatter->parseCurrency($input, $this->ccy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected function format(float|int $phpVal, ?\NumberFormatter $numberFormatter = null): false|string
|
||||||
|
{
|
||||||
|
if (!$this->showCcy) {
|
||||||
|
// If currency is not shown, create a new \NumberFormatter with style DECIMAL
|
||||||
|
$numberFormatter = new \NumberFormatter(
|
||||||
|
$this->getNumberFormatter()->getLocale(),
|
||||||
|
\NumberFormatter::DECIMAL,
|
||||||
|
$this->getNumberFormatter()->getPattern()
|
||||||
|
);
|
||||||
|
return parent::format($phpVal, $numberFormatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($numberFormatter === null) {
|
||||||
|
$numberFormatter = $this->getNumberFormatter();
|
||||||
|
}
|
||||||
|
return $numberFormatter->formatCurrency($phpVal, $this->ccy);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter\Exception;
|
||||||
|
|
||||||
|
class TypeErrorException extends \RuntimeException
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,281 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter;
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse and format float numbers. This class is also used as base for IntegerFormatter and
|
||||||
|
* CurrencyFormatter.
|
||||||
|
*
|
||||||
|
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
*/
|
||||||
|
class FloatFormatter extends AbstractFormatter implements FormatterInterface
|
||||||
|
{
|
||||||
|
private \NumberFormatter $numberFormatter;
|
||||||
|
protected int $parseType = \NumberFormatter::TYPE_DOUBLE;
|
||||||
|
protected int $formatterStyle = \NumberFormatter::DECIMAL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize PHP \NumberFormatter.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function init(): void
|
||||||
|
{
|
||||||
|
$this->setMinDigits(0);
|
||||||
|
$this->setMaxDigits(100);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function isStrictValidPhpVal($input): bool
|
||||||
|
{
|
||||||
|
return is_numeric($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse string from user input and store as float in object.
|
||||||
|
* If parsing fails, an Exception is thrown.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function parseUserInput(string $input): self
|
||||||
|
{
|
||||||
|
// Sanitize string
|
||||||
|
$input = $this->sanitizeInputString($input);
|
||||||
|
|
||||||
|
if ($input === '') {
|
||||||
|
// Check if user has entered an empty value and we are in strictness MODE_NULL
|
||||||
|
if ($this->getStrictness() == FormatterMode::MODE_NULL) {
|
||||||
|
$this->setParsedValue(null);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if user has entered an empty string and we are in strictness MODE_EMPTY
|
||||||
|
if ($this->getStrictness() == FormatterMode::MODE_EMPTY) {
|
||||||
|
$this->setParsedValue('');
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
// User has entered an empty string, but this is not allowed in strictness MODE_STRICT
|
||||||
|
throw new TypeErrorException(
|
||||||
|
"Value " . var_export($input, true) . " is not a valid type for " . get_class(
|
||||||
|
$this
|
||||||
|
) . " with strictness {$this->getStrictness()->name}"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// From here on, $input must contain a parseable input
|
||||||
|
|
||||||
|
if (($output = $this->parse($input)) === false) {
|
||||||
|
throw new \RuntimeException("{$this->getNumberFormatter()->getErrorMessage()}. \$input={$input}");
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->setParsedValue($output);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string representing the PHP value as a formatted value.
|
||||||
|
* Throws an Exception if no value was set before or the value is of the wrong type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function formatForUser(): string
|
||||||
|
{
|
||||||
|
return ($this->isNullValidPhpValue($this->getPhpVal()) || $this->isEmptyValidPhpValue($this->getPhpVal()))
|
||||||
|
? ''
|
||||||
|
: $this->format($this->getPhpVal());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string that can be used in an SQL query to format the value for presentation to a User.
|
||||||
|
* Should return the same string as if it was formatted by FormatterInterface::formatForUser(), but directly from
|
||||||
|
* the database.
|
||||||
|
* This function does not need a native PHP value, but a table column is needed.
|
||||||
|
*
|
||||||
|
* @param string $col
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function formatForUserWithSqlStatement(string $col): string
|
||||||
|
{
|
||||||
|
$min_decimals = $this->getNumberFormatter()->getAttribute(\NumberFormatter::MIN_FRACTION_DIGITS);
|
||||||
|
$max_decimals = $this->getNumberFormatter()->getAttribute(\NumberFormatter::MAX_FRACTION_DIGITS);
|
||||||
|
return ("FORMAT({$col},LEAST('{$max_decimals}',GREATEST('{$min_decimals}',LENGTH(TRIM(TRAILING '0' FROM SUBSTRING_INDEX(CAST({$col} AS CHAR),'.',-1))))),'{$this->getLocale()}')");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum displayed fraction digits for formatted output.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setMinDigits(int $digits): self
|
||||||
|
{
|
||||||
|
$this->getNumberFormatter()->setAttribute(\NumberFormatter::MIN_FRACTION_DIGITS, $digits);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum displayed fraction digits for formatted output.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setMaxDigits(int $digits): self
|
||||||
|
{
|
||||||
|
$this->getNumberFormatter()->setAttribute(\NumberFormatter::MAX_FRACTION_DIGITS, $digits);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum displayed integer digits for formatted output.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setMinIntDigits(int $digits): self
|
||||||
|
{
|
||||||
|
$this->getNumberFormatter()->setAttribute(\NumberFormatter::MIN_INTEGER_DIGITS, $digits);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum displayed integer digits for formatted output.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setMaxIntDigits(int $digits): self
|
||||||
|
{
|
||||||
|
$this->getNumberFormatter()->setAttribute(\NumberFormatter::MAX_INTEGER_DIGITS, $digits);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the minimum displayed significant digits for formatted output.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setMinSignificantDigits(int $digits): self
|
||||||
|
{
|
||||||
|
$this->getNumberFormatter()->setAttribute(\NumberFormatter::MIN_SIGNIFICANT_DIGITS, $digits);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum displayed significant digits for formatted output.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return $this
|
||||||
|
*/
|
||||||
|
public function setMaxSignificantDigits(int $digits): self
|
||||||
|
{
|
||||||
|
$this->getNumberFormatter()->setAttribute(\NumberFormatter::MAX_SIGNIFICANT_DIGITS, $digits);
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a \NumberFormatter object from cache. If the object does not exist, it is created first.
|
||||||
|
*
|
||||||
|
* @return \NumberFormatter
|
||||||
|
*/
|
||||||
|
protected function getNumberFormatter(): \NumberFormatter
|
||||||
|
{
|
||||||
|
if (!isset($this->numberFormatter)) {
|
||||||
|
$this->numberFormatter = new \NumberFormatter($this->getLocale(), $this->formatterStyle);
|
||||||
|
$this->numberFormatter->setAttribute(\NumberFormatter::LENIENT_PARSE, 1);
|
||||||
|
}
|
||||||
|
return $this->numberFormatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
protected function sanitizeInputString(string $string): string
|
||||||
|
{
|
||||||
|
return trim(strtolower(stripslashes(strval($string))), "abcdefghijklmnopqrstuvwxyz \t\n\r\0\x0B");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal parse function. Calls \NumberFormatter::parse().
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
* @param \NumberFormatter|null $numberFormatter
|
||||||
|
*
|
||||||
|
* @return false|float|int
|
||||||
|
*/
|
||||||
|
protected function parse(string $input, \NumberFormatter|null $numberFormatter = null): false|float|int
|
||||||
|
{
|
||||||
|
if ($numberFormatter === null) {
|
||||||
|
$numberFormatter = $this->getNumberFormatter();
|
||||||
|
}
|
||||||
|
if (($output = $numberFormatter->parse($input, $this->parseType)) === false) {
|
||||||
|
// could not parse number
|
||||||
|
// as a last resort, try to parse the number with locale de_DE
|
||||||
|
// This is necessary, because of many str_replace, where dot is replaced with comma
|
||||||
|
$numFmt = new \NumberFormatter('de_DE', \NumberFormatter::DECIMAL);
|
||||||
|
$output = $numFmt->parse($input, $this->parseType);
|
||||||
|
}
|
||||||
|
return $output;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal format function. Calls \NumberFormatter::format().
|
||||||
|
*
|
||||||
|
* @param float|int $phpVal
|
||||||
|
* @param \NumberFormatter|null $numberFormatter
|
||||||
|
*
|
||||||
|
* @return false|string
|
||||||
|
*/
|
||||||
|
protected function format(float|int $phpVal, \NumberFormatter|null $numberFormatter = null): false|string
|
||||||
|
{
|
||||||
|
if ($numberFormatter === null) {
|
||||||
|
$numberFormatter = $this->getNumberFormatter();
|
||||||
|
}
|
||||||
|
return $numberFormatter->format($phpVal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,84 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FormatterInterface defines the mandatory interface each formatter has to provide.
|
||||||
|
*
|
||||||
|
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
*/
|
||||||
|
interface FormatterInterface
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Parse string from user input and store as desired type in object.
|
||||||
|
* If parsing fails, an Exception is thrown.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function parseUserInput(string $input): self;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the native PHP value in the formatter.
|
||||||
|
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return self
|
||||||
|
*/
|
||||||
|
public function setPhpVal(mixed $input): self;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the native PHP value from the formatter.
|
||||||
|
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||||
|
*
|
||||||
|
* @return mixed
|
||||||
|
*/
|
||||||
|
public function getPhpVal(): mixed;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string representing the PHP value as a formatted value.
|
||||||
|
* Throws an Exception if no value was set before or the value is of the wrong type.
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function formatForUser(): string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a string that can be used in an SQL query to format the value for presentation to a User.
|
||||||
|
* Should return the same string as if it was formatted by FormatterInterface::formatForUser(), but directly from
|
||||||
|
* the database.
|
||||||
|
* This function does not need a native PHP value, but a table column is needed.
|
||||||
|
*
|
||||||
|
* @param string $col
|
||||||
|
*
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
public function formatForUserWithSqlStatement(string $col): string;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test $input for the correct (strict) type the class supports. Return false otherwise.
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isStrictValidPhpVal($input): bool;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter;
|
||||||
|
|
||||||
|
enum FormatterMode
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Only values representing the class type are allowed for input and output. This means, you can only store a
|
||||||
|
* float (or it's localized string representation) to a FloatFormatter).
|
||||||
|
*/
|
||||||
|
case MODE_STRICT;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow NULL as valid value in addition to the formatter type. If the user enters an empty string, this results
|
||||||
|
* in a PHP value of NULL and vice versa.
|
||||||
|
*/
|
||||||
|
case MODE_NULL;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow an empty string in addition to the formatter type. If the user entern an empty string, this results in
|
||||||
|
* an emtpy string as PHP value and vice versa.
|
||||||
|
*/
|
||||||
|
case MODE_EMPTY;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Formatter;
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||||
|
|
||||||
|
class IntegerFormatter extends FloatFormatter
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
protected function init(): void
|
||||||
|
{
|
||||||
|
$this->parseType = \NumberFormatter::TYPE_INT64;
|
||||||
|
parent::init();
|
||||||
|
parent::setMaxDigits(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For IntegerFormatter, strip decimals from $input if a number is given.
|
||||||
|
*
|
||||||
|
* @param mixed $input
|
||||||
|
*
|
||||||
|
* @return AbstractFormatter
|
||||||
|
*/
|
||||||
|
public function setPhpVal(mixed $input): AbstractFormatter
|
||||||
|
{
|
||||||
|
return parent::setPhpVal(is_numeric($input) ? intval($input) : $input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check if $input is an integer.
|
||||||
|
*
|
||||||
|
* @param $input
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function isStrictValidPhpVal($input): bool
|
||||||
|
{
|
||||||
|
return is_integer($input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't allow setting of min digits.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||||
|
*/
|
||||||
|
public function setMinDigits(int $digits): \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Don't allow setting of max digits.
|
||||||
|
*
|
||||||
|
* @param int $digits
|
||||||
|
*
|
||||||
|
* @return \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||||
|
*/
|
||||||
|
|
||||||
|
public function setMaxDigits(int $digits): \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||||
|
{
|
||||||
|
return $this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n;
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||||
|
use Xentral\Components\I18n\Formatter\FormatterInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This service creates formatters for localized input and output.
|
||||||
|
*
|
||||||
|
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
*/
|
||||||
|
class FormatterService
|
||||||
|
{
|
||||||
|
private string $locale;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a FormatterService object.
|
||||||
|
*
|
||||||
|
* @param string $locale
|
||||||
|
*/
|
||||||
|
public function __construct(string $locale)
|
||||||
|
{
|
||||||
|
$this->locale = $locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory for FormatterInterface objects. There will be a FormatterInterface object for every data type
|
||||||
|
* necessary.
|
||||||
|
*
|
||||||
|
* @param string $type
|
||||||
|
*
|
||||||
|
* @return FormatterInterface
|
||||||
|
*/
|
||||||
|
public function factory(string $type): FormatterInterface
|
||||||
|
{
|
||||||
|
return new $type($this->locale);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut function for creating a FloatFormatter and parsing a user input.
|
||||||
|
*
|
||||||
|
* @param string $input
|
||||||
|
*
|
||||||
|
* @return FloatFormatter
|
||||||
|
*/
|
||||||
|
public function floatFromUserInput(string $input): FloatFormatter
|
||||||
|
{
|
||||||
|
$formatter = new FloatFormatter($this->locale);
|
||||||
|
$formatter->parseUserInput($input);
|
||||||
|
return $formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut function for creating a FloatFormatter and setting a PHP value.
|
||||||
|
*
|
||||||
|
* @param float $input
|
||||||
|
*
|
||||||
|
* @return FloatFormatter
|
||||||
|
*/
|
||||||
|
public function floatFromPhpVal(float $input): FloatFormatter
|
||||||
|
{
|
||||||
|
$formatter = $this->factory(FloatFormatter::class);
|
||||||
|
$formatter->setPhpVal($input);
|
||||||
|
return $formatter;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,155 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Test;
|
||||||
|
|
||||||
|
require(__DIR__ . '/../../../bootstrap.php');
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\CurrencyFormatter;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Xentral\Components\I18n\Formatter\FormatterMode;
|
||||||
|
|
||||||
|
class CurrencyFormatterTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testStrictModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234,56 EUR', $output);
|
||||||
|
|
||||||
|
$floatFormatter = new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234 EUR', $output);
|
||||||
|
|
||||||
|
$floatFormatter = new CurrencyFormatter('de_CH', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('CHF 1’234.56', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithValueWithoutCCY()
|
||||||
|
{
|
||||||
|
$floatFormatter = new CurrencyFormatter('de_CH', FormatterMode::MODE_STRICT);
|
||||||
|
$floatFormatter->hideCurrency();
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1’234.56', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56 EUR')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234.56, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('EUR 1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithValueInputWithoutCCY()
|
||||||
|
{
|
||||||
|
$floatFormatter = (new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT))->hideCurrency();
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234.56, $output);
|
||||||
|
|
||||||
|
$floatFormatter = (new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT))->hideCurrency();
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testCanParseOwnOutput()
|
||||||
|
{
|
||||||
|
$value = 1234567.89;
|
||||||
|
$locale = 'de_DE';
|
||||||
|
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
|
||||||
|
$locale = 'de_CH';
|
||||||
|
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
|
||||||
|
$locale = 'de_AT';
|
||||||
|
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testCanParseOwnOutputWithoutCCY()
|
||||||
|
{
|
||||||
|
$value = 1234567.89;
|
||||||
|
$locale = 'de_DE';
|
||||||
|
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||||
|
$floatFormatter1->hideCurrency();
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||||
|
$floatFormatter2->hideCurrency();
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
|
||||||
|
$locale = 'de_CH';
|
||||||
|
$floatFormatter1 = (new CurrencyFormatter($locale))->hideCurrency();
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||||
|
$floatFormatter2->hideCurrency();
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
|
||||||
|
$locale = 'de_AT';
|
||||||
|
$floatFormatter1 = (new CurrencyFormatter($locale))->hideCurrency();
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
$floatFormatter1->hideCurrency();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = (new CurrencyFormatter($locale))->hideCurrency();
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,307 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Test;
|
||||||
|
|
||||||
|
require(__DIR__ . '/../../../bootstrap.php');
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||||
|
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
use Xentral\Components\I18n\Formatter\FormatterMode;
|
||||||
|
|
||||||
|
class FloatFormatterTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testStrictModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234,56', $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234.56, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithValueInputNoDecimals()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithNull()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithNullInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithEmpty()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testStrictModeWithEmptyInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testNullModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234,56', $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testNullModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234.56, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testNullModeWithNull()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testNullModeWithNullInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertNull($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testNullModeWithEmpty()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testNullModeWithEmptyInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertNull($output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testEmptyModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->setPhpVal(1234.56)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234,56', $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->setPhpVal(1234)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testEmptyModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234.56, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsFloat($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testEmptyModeWithNull()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testEmptyModeWithNullInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testEmptyModeWithEmpty()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testEmptyModeWithEmptyInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testCanParseOwnOutput()
|
||||||
|
{
|
||||||
|
$value = 1234567.89;
|
||||||
|
$locale = 'de_DE';
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new FloatFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
|
||||||
|
$locale = 'de_CH';
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new FloatFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
|
||||||
|
$locale = 'de_AT';
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new FloatFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals($value, $input);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testCanSetDigits()
|
||||||
|
{
|
||||||
|
$value = 1234567.8901234;
|
||||||
|
$locale = 'de_DE';
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(4)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.567,8901', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(3)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.567,89', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(3)->setMinDigits(3)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.567,890', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMinDigits(10)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.567,8901234000', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new FloatFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(0)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.568', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,144 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Test;
|
||||||
|
|
||||||
|
require(__DIR__ . '/../../../bootstrap.php');
|
||||||
|
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||||
|
use Xentral\Components\I18n\FormatterService;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class FormatterServiceTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testCanCreateFormatterService()
|
||||||
|
{
|
||||||
|
$formatterService = new FormatterService('de_DE');
|
||||||
|
$this->assertInstanceOf(FormatterService::class, $formatterService);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testFloatFromUserInput()
|
||||||
|
{
|
||||||
|
$formatterService = new FormatterService('de_DE');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1.234,56");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234.56, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_DE');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1234,56");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234.56, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_DE');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1.234.567,89");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234567.89, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_DE');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1234567,89");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234567.89, $phpVal);
|
||||||
|
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_CH');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1'234.56");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234.56, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_CH');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1234.56");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234.56, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_CH');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1'234'567.89");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234567.89, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_CH');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1234567.89");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234567.89, $phpVal);
|
||||||
|
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_AT');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1 234,56");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234.56, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_AT');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1234,56");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234.56, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_AT');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1 234 567,89");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234567.89, $phpVal);
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_AT');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromUserInput("1234567,89");
|
||||||
|
$phpVal = $floatFormatter->getPhpVal();
|
||||||
|
$this->assertIsFloat($phpVal);
|
||||||
|
$this->assertEquals(1234567.89, $phpVal);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public function testFloatFromPhpVal()
|
||||||
|
{
|
||||||
|
$formatterService = new FormatterService('de_DE');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromPhpVal(1234567.89);
|
||||||
|
$formattedString = $floatFormatter->formatForUser();
|
||||||
|
$this->assertIsString($formattedString);
|
||||||
|
$this->assertEquals("1.234.567,89", $formattedString);
|
||||||
|
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_CH');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromPhpVal(1234567.89);
|
||||||
|
$formattedString = $floatFormatter->formatForUser();
|
||||||
|
$this->assertIsString($formattedString);
|
||||||
|
$this->assertEquals("1’234’567.89", $formattedString);
|
||||||
|
|
||||||
|
|
||||||
|
$formatterService = new FormatterService('de_AT');
|
||||||
|
/** @var FloatFormatter $floatFormatter */
|
||||||
|
$floatFormatter = $formatterService->floatFromPhpVal(1234567.89);
|
||||||
|
$formattedString = $floatFormatter->formatForUser();
|
||||||
|
$this->assertIsString($formattedString);
|
||||||
|
$this->assertEquals("1 234 567,89", $formattedString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,247 @@
|
||||||
|
<?php
|
||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||||
|
* SPDX-License-Identifier: AGPL-3.0-only
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace Xentral\Components\I18n\Test;
|
||||||
|
|
||||||
|
require(__DIR__ . '/../../../bootstrap.php');
|
||||||
|
|
||||||
|
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||||
|
use Xentral\Components\I18n\Formatter\FormatterMode;
|
||||||
|
use Xentral\Components\I18n\Formatter\IntegerFormatter;
|
||||||
|
use PHPUnit\Framework\TestCase;
|
||||||
|
|
||||||
|
class IntegerFormatterTest extends TestCase
|
||||||
|
{
|
||||||
|
public function testStrictModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStrictModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsInt($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsInt($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testStrictModeWithNull()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||||
|
}
|
||||||
|
public function testStrictModeWithNullInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
}
|
||||||
|
public function testStrictModeWithEmpty()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||||
|
}
|
||||||
|
public function testStrictModeWithEmptyInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
}
|
||||||
|
public function testNullModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNullModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsInt($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsInt($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testNullModeWithNull()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
public function testNullModeWithNullInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertNull($output);
|
||||||
|
}
|
||||||
|
public function testNullModeWithEmpty()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||||
|
}
|
||||||
|
public function testNullModeWithEmptyInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertNull($output);
|
||||||
|
}
|
||||||
|
public function testEmptyModeWithValue()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->setPhpVal(1234.56)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->setPhpVal(1234)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('1.234', $output);
|
||||||
|
}
|
||||||
|
public function testEmptyModeWithValueInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsInt($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
|
||||||
|
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsInt($output);
|
||||||
|
$this->assertEquals(1234, $output);
|
||||||
|
}
|
||||||
|
public function testEmptyModeWithNull()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$this->expectException(TypeErrorException::class);
|
||||||
|
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||||
|
}
|
||||||
|
public function testEmptyModeWithNullInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
public function testEmptyModeWithEmpty()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
public function testEmptyModeWithEmptyInput()
|
||||||
|
{
|
||||||
|
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||||
|
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertIsString($output);
|
||||||
|
$this->assertEquals('', $output);
|
||||||
|
}
|
||||||
|
public function testCanParseOwnOutput()
|
||||||
|
{
|
||||||
|
$value = 1234567.89;
|
||||||
|
$locale = 'de_DE';
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new IntegerFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals(intval($value), $input);
|
||||||
|
|
||||||
|
$locale = 'de_CH';
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new IntegerFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals(intval($value), $input);
|
||||||
|
|
||||||
|
$locale = 'de_AT';
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$floatFormatter2 = new IntegerFormatter($locale);
|
||||||
|
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||||
|
var_dump($input);
|
||||||
|
$this->assertEquals(intval($value), $input);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testCanSetDigits()
|
||||||
|
{
|
||||||
|
$value = 1234567.8901234;
|
||||||
|
$locale = 'de_DE';
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMinIntDigits(10)->setMaxDigits(4)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('0.001.234.567', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxIntDigits(4)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('4.567', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(3)->setMinDigits(3)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.567', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMaxSignificantDigits(3)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.230.000', $output);
|
||||||
|
|
||||||
|
$floatFormatter1 = new IntegerFormatter($locale);
|
||||||
|
$output = $floatFormatter1->setPhpVal($value)->setMinSignificantDigits(3)->formatForUser();
|
||||||
|
var_dump($output);
|
||||||
|
$this->assertEquals('1.234.567', $output);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue