From a64345976e080eda0dfb3b0d5adb22dfdf59af99 Mon Sep 17 00:00:00 2001 From: Roland Rusch Date: Sat, 26 Aug 2023 21:18:37 +0200 Subject: [PATCH] RETROTEC-AG/OpenXE#18 Number parser implementieren --- classes/Components/I18n/Bootstrap.php | 19 +- .../I18n/Formatter/AbstractFormatter.php | 168 ++++++++++ .../I18n/Formatter/CurrencyFormatter.php | 142 ++++++++ .../Exception/TypeErrorException.php | 14 + .../I18n/Formatter/FloatFormatter.php | 281 ++++++++++++++++ .../I18n/Formatter/FormatterInterface.php | 84 +++++ .../I18n/Formatter/FormatterMode.php | 31 ++ .../I18n/Formatter/IntegerFormatter.php | 82 +++++ classes/Components/I18n/FormatterService.php | 83 +++++ .../I18n/Test/CurrencyFormatterTest.php | 155 +++++++++ .../I18n/Test/FloatFormatterTest.php | 307 ++++++++++++++++++ .../I18n/Test/FormatterServiceTest.php | 144 ++++++++ .../I18n/Test/IntegerFormatterTest.php | 247 ++++++++++++++ 13 files changed, 1754 insertions(+), 3 deletions(-) create mode 100644 classes/Components/I18n/Formatter/AbstractFormatter.php create mode 100644 classes/Components/I18n/Formatter/CurrencyFormatter.php create mode 100644 classes/Components/I18n/Formatter/Exception/TypeErrorException.php create mode 100644 classes/Components/I18n/Formatter/FloatFormatter.php create mode 100644 classes/Components/I18n/Formatter/FormatterInterface.php create mode 100644 classes/Components/I18n/Formatter/FormatterMode.php create mode 100644 classes/Components/I18n/Formatter/IntegerFormatter.php create mode 100644 classes/Components/I18n/FormatterService.php create mode 100644 classes/Components/I18n/Test/CurrencyFormatterTest.php create mode 100644 classes/Components/I18n/Test/FloatFormatterTest.php create mode 100644 classes/Components/I18n/Test/FormatterServiceTest.php create mode 100644 classes/Components/I18n/Test/IntegerFormatterTest.php diff --git a/classes/Components/I18n/Bootstrap.php b/classes/Components/I18n/Bootstrap.php index 803ac290..2a6b6c3d 100644 --- a/classes/Components/I18n/Bootstrap.php +++ b/classes/Components/I18n/Bootstrap.php @@ -1,5 +1,5 @@ * SPDX-License-Identifier: AGPL-3.0-only */ @@ -16,7 +16,7 @@ use Xentral\Core\DependencyInjection\ServiceContainer; /** * Factory for localization object. * - * @see Localization + * @see Localization * @author Roland Rusch, easy-smart solution GmbH */ final class Bootstrap @@ -28,6 +28,7 @@ final class Bootstrap { return [ 'Localization' => 'onInitLocalization', + 'FormatterService' => 'onInitFormatterService', ]; } @@ -111,7 +112,9 @@ final class Bootstrap /** @var Database $db */ $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 if ($firmaLang = self::findLanguage(strval($app->erp->Firmendaten('preferredLanguage')))) { $config[Localization::LANGUAGE_DEFAULT] = $firmaLang[Iso639\Key::ALPHA_3]; @@ -146,4 +149,14 @@ final class Bootstrap // Create Localization object 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); + } + } diff --git a/classes/Components/I18n/Formatter/AbstractFormatter.php b/classes/Components/I18n/Formatter/AbstractFormatter.php new file mode 100644 index 00000000..a2955f5f --- /dev/null +++ b/classes/Components/I18n/Formatter/AbstractFormatter.php @@ -0,0 +1,168 @@ + + * 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 + */ +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); + } + +} \ No newline at end of file diff --git a/classes/Components/I18n/Formatter/CurrencyFormatter.php b/classes/Components/I18n/Formatter/CurrencyFormatter.php new file mode 100644 index 00000000..7cba2254 --- /dev/null +++ b/classes/Components/I18n/Formatter/CurrencyFormatter.php @@ -0,0 +1,142 @@ + + * 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); + } + + +} \ No newline at end of file diff --git a/classes/Components/I18n/Formatter/Exception/TypeErrorException.php b/classes/Components/I18n/Formatter/Exception/TypeErrorException.php new file mode 100644 index 00000000..bf398911 --- /dev/null +++ b/classes/Components/I18n/Formatter/Exception/TypeErrorException.php @@ -0,0 +1,14 @@ + + * SPDX-License-Identifier: AGPL-3.0-only + */ + +declare(strict_types=1); + +namespace Xentral\Components\I18n\Formatter\Exception; + +class TypeErrorException extends \RuntimeException +{ + +} \ No newline at end of file diff --git a/classes/Components/I18n/Formatter/FloatFormatter.php b/classes/Components/I18n/Formatter/FloatFormatter.php new file mode 100644 index 00000000..501ba423 --- /dev/null +++ b/classes/Components/I18n/Formatter/FloatFormatter.php @@ -0,0 +1,281 @@ + + * 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 + */ +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); + } +} \ No newline at end of file diff --git a/classes/Components/I18n/Formatter/FormatterInterface.php b/classes/Components/I18n/Formatter/FormatterInterface.php new file mode 100644 index 00000000..036dd408 --- /dev/null +++ b/classes/Components/I18n/Formatter/FormatterInterface.php @@ -0,0 +1,84 @@ + + * 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 + */ +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; +} \ No newline at end of file diff --git a/classes/Components/I18n/Formatter/FormatterMode.php b/classes/Components/I18n/Formatter/FormatterMode.php new file mode 100644 index 00000000..bb28b329 --- /dev/null +++ b/classes/Components/I18n/Formatter/FormatterMode.php @@ -0,0 +1,31 @@ + + * 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; +} diff --git a/classes/Components/I18n/Formatter/IntegerFormatter.php b/classes/Components/I18n/Formatter/IntegerFormatter.php new file mode 100644 index 00000000..efafbd4f --- /dev/null +++ b/classes/Components/I18n/Formatter/IntegerFormatter.php @@ -0,0 +1,82 @@ + + * 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; + } + + +} \ No newline at end of file diff --git a/classes/Components/I18n/FormatterService.php b/classes/Components/I18n/FormatterService.php new file mode 100644 index 00000000..7643a1eb --- /dev/null +++ b/classes/Components/I18n/FormatterService.php @@ -0,0 +1,83 @@ + + * 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 + */ +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; + } + + +} \ No newline at end of file diff --git a/classes/Components/I18n/Test/CurrencyFormatterTest.php b/classes/Components/I18n/Test/CurrencyFormatterTest.php new file mode 100644 index 00000000..94c420c8 --- /dev/null +++ b/classes/Components/I18n/Test/CurrencyFormatterTest.php @@ -0,0 +1,155 @@ + + * 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); + } + +} diff --git a/classes/Components/I18n/Test/FloatFormatterTest.php b/classes/Components/I18n/Test/FloatFormatterTest.php new file mode 100644 index 00000000..ce2fc93d --- /dev/null +++ b/classes/Components/I18n/Test/FloatFormatterTest.php @@ -0,0 +1,307 @@ + + * 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); + } + +} diff --git a/classes/Components/I18n/Test/FormatterServiceTest.php b/classes/Components/I18n/Test/FormatterServiceTest.php new file mode 100644 index 00000000..51ec905d --- /dev/null +++ b/classes/Components/I18n/Test/FormatterServiceTest.php @@ -0,0 +1,144 @@ + + * 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); + } +} diff --git a/classes/Components/I18n/Test/IntegerFormatterTest.php b/classes/Components/I18n/Test/IntegerFormatterTest.php new file mode 100644 index 00000000..16c27885 --- /dev/null +++ b/classes/Components/I18n/Test/IntegerFormatterTest.php @@ -0,0 +1,247 @@ + + * 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); + } + +}