This commit is contained in:
Roland Rusch 2023-08-30 14:50:02 +02:00 committed by GitHub
commit 124c243a12
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 2501 additions and 320 deletions

View File

@ -1,5 +1,5 @@
<?php
/**
/*
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
* 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 <roland.rusch@easy-smart.ch>
*/
final class Bootstrap
@ -28,6 +28,7 @@ final class Bootstrap
{
return [
'Localization' => 'onInitLocalization',
'FormatterService' => 'onInitFormatterService',
];
}
@ -61,7 +62,7 @@ final class Bootstrap
$subject = strtolower($lang);
foreach ((new Iso639()) as $key => $val) {
if (array_filter($val, function ($str) use ($subject) {
return $str && ((strtolower($str) == $subject) || (self::replaceUmlauts(strtolower($str)) == $subject));
return $str && ((strtolower($str) == $subject) || (strtolower(self::replaceUmlauts($str)) == $subject));
})) {
return $val;
}
@ -83,7 +84,7 @@ final class Bootstrap
$subject = strtolower($region);
foreach ((new Iso3166()) as $key => $val) {
if (array_filter($val, function ($str) use ($subject) {
return $str && ((strtolower($str) == $subject) || (self::replaceUmlauts(strtolower($str)) == $subject));
return $str && ((strtolower($str) == $subject) || (strtolower(self::replaceUmlauts($str)) == $subject));
})) {
return $val;
}
@ -111,16 +112,16 @@ final class Bootstrap
/** @var Database $db */
$db = $container->get('Database');
$config=[];
$firmaLang=null;
$firmaRegion=null;
$config = [];
$firmaLang = null;
$firmaRegion = null;
// Get language from system settings and normalize to 3-letter-code and 2-letter-code
if ($firmaLang = self::findLanguage($app->erp->Firmendaten('preferredLanguage'))) {
if ($firmaLang = self::findLanguage(strval($app->erp->Firmendaten('preferredLanguage')))) {
$config[Localization::LANGUAGE_DEFAULT] = $firmaLang[Iso639\Key::ALPHA_3];
}
// Get region from system settings and normalize to 2-letter-code
if ($firmaLang && ($firmaRegion = self::findRegion($app->erp->Firmendaten('land')))) {
if ($firmaLang && ($firmaRegion = self::findRegion(strval($app->erp->Firmendaten('land'))))) {
$config[Localization::LOCALE_DEFAULT] = "{$firmaLang[Iso639\Key::ALPHA_2]}_{$firmaRegion[Iso3166\Key::ALPHA_2]}";
}
@ -135,12 +136,12 @@ final class Bootstrap
);
// Get language from user account and normalize to 3-letter-code and 2-letter-code
if ($userLang = self::findLanguage($user->GetSprache())) {
if ($userLang = self::findLanguage(strval($user->GetSprache()))) {
$usersettings['language'] = $userLang[Iso639\Key::ALPHA_3];
}
// Get region from user account and normalize to 2-letter-code
if ($userLang && ($userRegion = self::findRegion($userAddress['land']))) {
if ($userLang && ($userRegion = self::findRegion(strval($userAddress['land'])))) {
$usersettings['locale'] = "{$userLang[Iso639\Key::ALPHA_2]}_{$userRegion[Iso3166\Key::ALPHA_2]}";
}
}
@ -148,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);
}
}

View File

@ -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\Exception;
class LocaleNotSetException extends \RuntimeException
{
}

View File

@ -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);
}
}

View File

@ -0,0 +1,163 @@
<?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);
}
/**
* 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.
*
* @TODO This function is not complete. It does not add a currency symbol.
*
* @param string $col
*
* @return string
* @deprecated
*
*/
public function formatForUserWithSqlStatement(string $col): string
{
return parent::formatForUserWithSqlStatement($col);
}
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);
}
}

View File

@ -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
{
}

View File

@ -0,0 +1,327 @@
<?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);
$sql = "FORMAT({$col},LEAST('{$max_decimals}',GREATEST('{$min_decimals}',LENGTH(TRIM(TRAILING '0' FROM SUBSTRING_INDEX(CAST({$col} AS CHAR),'.',-1))))),'{$this->getLocale()}')";
if (!$this->getNumberFormatter()->getAttribute(\NumberFormatter::GROUPING_USED)) {
$sql = "REPLACE({$sql}, '{$this->getNumberFormatter()->getSymbol(\NumberFormatter::GROUPING_SEPARATOR_SYMBOL)}', '')";
}
return $sql;
}
/**
* 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 the locale defined decimal symbol.
*
* @return string
*/
public function getDecimalSymbol(): string
{
return $this->getNumberFormatter()->getSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL);
}
/**
* Overwrite the locale defined decimal symbol.
*
* @param string $symbol
*
* @return $this
*/
public function setDecimalSymbol(string $symbol): self
{
$this->getNumberFormatter()->setSymbol(\NumberFormatter::DECIMAL_SEPARATOR_SYMBOL, $symbol);
return $this;
}
/**
* Disable grouping (thousands).
*
* @return $this
*/
public function hideGrouping(): self
{
$this->getNumberFormatter()->setAttribute(\NumberFormatter::GROUPING_USED, 0);
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);
}
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -0,0 +1,336 @@
<?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\CurrencyFormatter;
use Xentral\Components\I18n\Formatter\FloatFormatter;
use Xentral\Components\I18n\Formatter\FormatterInterface;
use Xentral\Components\I18n\Formatter\FormatterMode;
use Xentral\Components\I18n\Formatter\IntegerFormatter;
/**
* 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;
}
/**
* Return the currently set locale.
*
* @return string
*/
public function getLocale(): string
{
return $this->locale;
}
/**
* Factory for FormatterInterface objects. There will be a FormatterInterface object for every data type
* necessary.
*
* @param string $type
* @param FormatterMode $strictness
*
* @return FormatterInterface
*/
public function factory(string $type, FormatterMode $strictness = FormatterMode::MODE_STRICT): FormatterInterface
{
return new $type($this->locale, $strictness);
}
/**
* Shortcut function for creating a FloatFormatter and parsing a user input.
*
* @param string $input
* @param FormatterMode $strictness
*
* @return FloatFormatter
*/
public function floatFromUserInput(
string $input,
FormatterMode $strictness = FormatterMode::MODE_NULL
): FloatFormatter {
$formatter = new FloatFormatter($this->locale, $strictness);
$formatter->parseUserInput($input);
return $formatter;
}
/**
* Shortcut function for creating a FloatFormatter and setting a PHP value.
*
* @param string|float|null $input
* @param FormatterMode $strictness
*
* @return FloatFormatter
*/
public function floatFromPhpVal(
string|null|float $input,
FormatterMode $strictness = FormatterMode::MODE_NULL
): FloatFormatter {
$formatter = $this->factory(FloatFormatter::class, $strictness);
$formatter->setPhpVal($input);
return $formatter;
}
/**
* Replace callback function for \FormActionHandler.
* Parses and Formats an integer and allows an empty string.
*
* @param int $toDatabase
* @param mixed $value
* @param $fromForm
*
* @return mixed|string
* @see \FormActionHandler
*/
public function replaceIntegerOrEmpty(int $toDatabase, mixed $value, $fromForm)
{
$formatter = new IntegerFormatter($this->locale, FormatterMode::MODE_EMPTY);
if (!is_numeric($value) || $fromForm) {
$formatter->parseUserInput(strval($value));
} else {
$formatter->setPhpVal($value);
}
if ($toDatabase) {
return $formatter->getPhpVal();
} else {
return $formatter->formatForUser();
}
}
/**
* Replace callback function for \FormActionHandler.
* Parses and Formats a float and allows an empty string.
* Output shows decimals, if present.
*
* @param int $toDatabase
* @param mixed $value
* @param $fromForm
*
* @return mixed|string
* @see \FormActionHandler
*/
public function replaceDecimalOrEmpty(int $toDatabase, mixed $value, $fromForm)
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
if (!is_numeric($value) || $fromForm) {
$formatter->parseUserInput(strval($value));
} else {
$formatter->setPhpVal(floatval($value));
}
if ($toDatabase) {
return $formatter->getPhpVal();
} else {
return $formatter->formatForUser();
}
}
/**
* Replace callback function for \FormActionHandler.
* Parses and Formats a float and allows an empty string.
* Output always shows at least 7 decimal.
*
* @param int $toDatabase
* @param mixed $value
* @param $fromForm
*
* @return mixed|string
* @see \FormActionHandler
*/
public function replaceDecimalGeoOrEmpty(int $toDatabase, mixed $value, $fromForm)
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
$formatter->setMinDigits(7);
if (!is_numeric($value) || $fromForm) {
$formatter->parseUserInput(strval($value));
} else {
$formatter->setPhpVal(floatval($value));
}
if ($toDatabase) {
return $formatter->getPhpVal();
} else {
return $formatter->formatForUser();
}
}
/**
* Replace callback function for \FormActionHandler.
* Parses and Formats a float and allows an empty string.
* Output always shows at least 1 decimal.
*
* @param int $toDatabase
* @param mixed $value
* @param $fromForm
*
* @return mixed|string
* @see \FormActionHandler
*/
public function replaceDecimalPercentOrEmpty(int $toDatabase, mixed $value, $fromForm)
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
$formatter->setMinDigits(1);
if (!is_numeric($value) || $fromForm) {
$formatter->parseUserInput(strval($value));
} else {
$formatter->setPhpVal(floatval($value));
}
if ($toDatabase) {
return $formatter->getPhpVal();
} else {
return $formatter->formatForUser();
}
}
/**
* Replace callback function for \FormActionHandler.
* Parses and Formats a float and allows an empty string.
*
* @param int $toDatabase
* @param mixed $value
* @param $fromForm
*
* @return mixed|string
* @see \FormActionHandler
*/
public function replaceCurrencyOrEmpty(int $toDatabase, mixed $value, $fromForm)
{
$formatter = (new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY));
$formatter->setMinDigits(2);
if (!is_numeric($value) || $fromForm) {
$formatter->parseUserInput(strval($value));
} else {
$formatter->setPhpVal(floatval($value));
}
if ($toDatabase) {
return $formatter->getPhpVal();
} else {
return $formatter->formatForUser();
}
}
/**
* Format a quantity value for output.
*
* @param mixed $menge
*
* @return string
*/
public function formatMenge(mixed $menge): string
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
$formatter->setPhpVal(floatval($menge));
return $formatter->formatForUser();
}
/**
* Parse a quantity from a form and parse for database input.
*
* @param mixed $string
*
* @return string|float|null
*/
public function parseMenge(mixed $string): string|null|float
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
$formatter->parseUserInput(strval($string));
return $formatter->getPhpVal();
}
/**
* Format a price value for output.
*
* @param mixed $menge
*
* @return string
*/
public function formatPreis(mixed $menge): string
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
$formatter->setMinDigits(2);
$formatter->setPhpVal(floatval($menge));
return $formatter->formatForUser();
}
/**
* Parse a price from a form and parse for database input.
*
* @param mixed $string
*
* @return string|float|null
*/
public function parsePreis(mixed $string): string|null|float
{
$formatter = new FloatFormatter($this->locale, FormatterMode::MODE_EMPTY);
$formatter->setMinDigits(2);
$formatter->parseUserInput(strval($string));
return $formatter->getPhpVal();
}
}

View File

@ -12,6 +12,7 @@ use Locale;
use Xentral\Components\Http\Request;
use Xentral\Components\Http\Session\Session;
use Xentral\Components\I18n\Exception\LanguageNotInitializedException;
use Xentral\Components\I18n\Exception\LocaleNotSetException;
use Xentral\Components\I18n\Exception\UnsupportedLocaleStringException;
/**
@ -31,7 +32,7 @@ final class Localization implements LocalizationInterface
private array $language = [];
private array $locale = [];
private string|null $locale;
@ -41,6 +42,11 @@ final class Localization implements LocalizationInterface
$this->session = $session;
$this->usersettings = $usersettings;
$this->config = $config;
// Set config if no default is given
$this->config[Localization::LOCALE_DEFAULT]=$this->config[Localization::LOCALE_DEFAULT] ?? 'de_DE';
$this->config[Localization::LANGUAGE_DEFAULT]=$this->config[Localization::LANGUAGE_DEFAULT] ?? 'deu';
$this->process();
}
@ -49,39 +55,48 @@ final class Localization implements LocalizationInterface
public function process()
{
// Hardcoded defaults if config is not available
$localeDefault = $this->config[Localization::LOCALE_DEFAULT] ?? 'de_DE';
// $localeDefault = $this->config[Localization::LOCALE_DEFAULT] ?? 'de_DE';
$localeAttrName = $this->config[Localization::LOCALE_ATTRIBUTE_NAME] ?? 'locale';
$langDefault = $this->config[Localization::LANGUAGE_DEFAULT] ?? 'deu';
$langAttrName = $this->config[Localization::LANGUAGE_ATTRIBUTE_NAME] ?? 'language';
$segmentName = 'i18n';
$this->setLocale((string)$this->config[Localization::LOCALE_DEFAULT]);
// Get the locale from the session, if available
if ($this->session && ($locale = $this->session->getValue($segmentName, $localeAttrName))) {
if ($this->session && ($sessionLocale = $this->session->getValue($segmentName, $localeAttrName))) {
$this->setLocale((string)$sessionLocale, $this->getLocale());
} else {
// Get locale from request, fallback to the user's browser preference
if ($this->request) {
$locale = $this->request->attributes->get(
$localeAttrName,
Locale::acceptFromHttp(
$this->request->getHeader('Accept-Language', $localeDefault)
) ?? $localeDefault
);
try {
$this->setLocale((string)$this->request->attributes->get($localeAttrName, ''));
} catch (UnsupportedLocaleStringException $e) {
$this->setLocale(
(string)
Locale::acceptFromHttp(
$this->request->getHeader('Accept-Language', '')
)
,
$this->getLocale()
);
}
} else {
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? $localeDefault);
$this->setLocale((string)Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? ''), $this->getLocale());
}
}
// Get locale from user
// This overrides all previous attempts to find a locale
if (array_key_exists('locale', $this->usersettings)) {
$locale = $this->usersettings['locale'];
$this->setLocale((string)$this->usersettings['locale'], $this->getLocale());
}
// Get locale from query string
// This overrides all previous attempts to find a locale
if ($this->request) {
$locale = $this->request->getParam($localeAttrName, $locale ?? $localeDefault);
$this->setLocale((string)$this->request->getParam($localeAttrName), $this->getLocale());
} else {
$locale = $_GET[$localeAttrName] ?? $locale ?? $localeDefault;
$this->setLocale((string)$_GET[$localeAttrName], $this->getLocale());
}
@ -90,9 +105,9 @@ final class Localization implements LocalizationInterface
} else {
// Get language from request, fallback to the current locale
if ($this->request) {
$language = $this->request->attributes->get($langAttrName, Locale::getPrimaryLanguage($locale));
$language = $this->request->attributes->get($langAttrName, Locale::getPrimaryLanguage($this->getLocale()));
} else {
$language = Locale::getPrimaryLanguage($locale);
$language = Locale::getPrimaryLanguage($this->getLocale());
}
}
// Get language from user
@ -114,22 +129,21 @@ final class Localization implements LocalizationInterface
// Store the locale and language to the LocalizationInterface
$this->setLanguage($language);
$this->setLocale($locale);
// Store the locale and language to the session
if ($this->session) {
$this->session->setValue($segmentName, $localeAttrName, $locale);
$this->session->setValue($segmentName, $langAttrName, $language);
$this->session->setValue($segmentName, $localeAttrName, $this->getLocale());
$this->session->setValue($segmentName, $langAttrName, $this->getLanguage());
}
// Store the locale and language as a request attribute
if ($this->request) {
$this->request->attributes->set($localeAttrName, $locale);
$this->request->attributes->set($langAttrName, $language);
$this->request->attributes->set($localeAttrName, $this->getLocale());
$this->request->attributes->set($langAttrName, $this->getLanguage());
}
// Set the default locale
Locale::setDefault($locale);
Locale::setDefault($this->getLocale());
// error_log(self::class . ": {$locale}");
}
@ -179,19 +193,42 @@ final class Localization implements LocalizationInterface
/**
* Set the locale.
*
* @param string $locale
* @param string $locale
* @param string|null $fallbackLocale
*/
public function setLocale(string $locale)
public function setLocale(string $locale, string|null $fallbackLocale = null): void
{
$parsedLocale = Locale::parseLocale($locale);
$locale = Locale::composeLocale([
'language' => $parsedLocale['language'],
'region' => $parsedLocale['region'],
]);
if(!empty($locale)) {
// Check if locale is already set
try {
if ($locale == $this->getLocale()) {
return;
}
} catch (LocaleNotSetException $e) {
};
// Parse and re-compose locale to make sure, it is sane
$parsedLocale = Locale::parseLocale($locale);
$composedLocale = Locale::composeLocale([
'language' => $parsedLocale['language'],
'region' => $parsedLocale['region'],
]);
} else {
$composedLocale=null;
}
if(!$locale) throw new UnsupportedLocaleStringException("The given locale string '{$locale}' is not supported");
// If sanity check fails, set fallbackLocale if present
// throw exception otherwise
if (!$composedLocale) {
if ($fallbackLocale === null) {
throw new UnsupportedLocaleStringException("The given locale string '{$locale}' is not supported");
} else {
$this->setLocale($fallbackLocale);
return;
}
}
$this->locale[Iso3166\Key::DEFAULT] = $locale;
$this->locale = $composedLocale;
}
@ -199,13 +236,14 @@ final class Localization implements LocalizationInterface
/**
* Return the locale string as defined by $key.
*
* @param string|null $key A constant from Iso3166\Key
*
* @return string
*/
public function getLocale(string $key = null): string
public function getLocale(): string
{
return $this->locale[Iso3166\Key::DEFAULT];
if (!isset($this->locale)) {
throw new LocaleNotSetException();
}
return $this->locale;
}
@ -222,7 +260,7 @@ final class Localization implements LocalizationInterface
$localization = clone $this;
// Find language from address array or keep current language
if (!$lang = Bootstrap::findLanguage($adresse['sprache'])) {
if (!$lang = Bootstrap::findLanguage($adresse['sprache'] ?? '')) {
$lang = Bootstrap::findLanguage($this->getLanguage());
}
if ($lang) {
@ -230,7 +268,7 @@ final class Localization implements LocalizationInterface
}
// Find region from address or keep current region
if (!$region = Bootstrap::findRegion($adresse['land'])) {
if (!$region = Bootstrap::findRegion($adresse['land'] ?? '')) {
$parsedLocale = Locale::parseLocale($this->getLocale());
$region = Bootstrap::findRegion($parsedLocale['region']);
}

View File

@ -45,18 +45,17 @@ interface LocalizationInterface
/**
* Set the locale.
*
* @param string $locale
* @param string $locale
* @param string|null $fallbackLocale
*/
public function setLocale(string $locale);
public function setLocale(string $locale, string|null $fallbackLocale=null);
/**
* Return the locale string as defined by $key.
*
* @param string|null $key A constant from Iso3166\Key
*
* @return string
*/
public function getLocale(string $key = null): string;
public function getLocale(): string;
}

View File

@ -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 1234.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('1234.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);
}
}

View File

@ -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);
}
}

View File

@ -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("1234567.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);
}
}

View File

@ -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);
}
}

View File

@ -75,7 +75,7 @@ class FiskalyTransferService
* @throws Exception
* @return Transaction
*
* @depracated
* @deprecated
*/
public function createTransactionFromSingleJournal(
int $cashierId,
@ -270,7 +270,7 @@ class FiskalyTransferService
* @throws Exception
* @return Transaction
*
* @depracated
* @deprecated
*/
public function transferPosSession($posSession): Transaction
{

View File

@ -474,9 +474,12 @@ class User
return $this->cache[$cacheKey]['name'];
}
/**
* @return array
* @deprecated Eine Liste der verfügbaren Sprachen sollte IMHO zentral im Übersetzer generiert werden.
*/
public function GetSprachen()
{
@ -505,15 +508,20 @@ class User
return $defaultLanguages;
}
/**
* @return string
* Die vom User gewählte Sprache zurückgeben.
* Null, falls die Sprache nicht erkannt wird.
*
* @return string|null
*/
public function GetSprache()
public function GetSprache(): string|null
{
$sprachen = $this->GetSprachen();
return reset($sprachen);
return \Xentral\Components\I18n\Bootstrap::findLanguage(
strval($this->GetField('sprachebevorzugen'))
)[Xentral\Components\I18n\Iso639\Key::DEFAULT];
}
/**

View File

@ -449,12 +449,6 @@ class YUI {
break;
case 2: // Betrag
$value = $this->app->erp->FromFormatZahlToDB($value);
if(strpos($value,','))
{
$value = str_replace(",", ".",str_replace('.','', $value));
}else{
$value = str_replace(",", ".", $value);
}
$this->app->DB->Update("UPDATE $table SET betrag='$value' WHERE id='$id' LIMIT 1");
$result = $this->app->DB->Select("SELECT ".$this->FormatPreis('betrag')." FROM $table WHERE id='$id' LIMIT 1");
break;
@ -476,19 +470,12 @@ class YUI {
case 2: // Menge
$value = $this->app->erp->FromFormatZahlToDB($value);
$value = str_replace(",", ".", $value);
$this->app->DB->Update("UPDATE $table SET menge='$value' WHERE id='$id' LIMIT 1");
$result = $this->app->DB->Select("SELECT ".$this->app->erp->FormatMenge("menge")." FROM $table WHERE id='$id' LIMIT 1");
break;
case 3: // Betrag
$value = $this->app->erp->FromFormatZahlToDB($value);
if(strpos($value,','))
{
$value = str_replace(",", ".",str_replace('.','', $value));
}else{
$value = str_replace(",", ".", $value);
}
$this->app->DB->Update("UPDATE $table SET betrag='$value' WHERE id='$id' LIMIT 1");
$result = $this->app->DB->Select("SELECT ".$this->FormatPreis('betrag')." FROM $table WHERE id='$id' LIMIT 1");
break;
@ -519,12 +506,6 @@ class YUI {
break;
case 4: // preis
$value = $this->app->erp->FromFormatZahlToDB($value);
if(strpos($value,','))
{
$value = str_replace(",", ".",str_replace('.','', $value));
}else{
$value = str_replace(",", ".", $value);
}
$this->app->DB->Update("UPDATE $table SET preis='$value' WHERE id='$id' LIMIT 1");
$result = $this->app->DB->Select("SELECT ".$this->FormatPreis('preis')." FROM $table WHERE id='$id' LIMIT 1");
break;
@ -544,7 +525,6 @@ class YUI {
break;
case 4: // Menge
$value = $this->app->erp->FromFormatZahlToDB($value);
$value = str_replace(',', '.', $value);
if($value < 0 ) {
$value=1;
}
@ -650,12 +630,6 @@ class YUI {
break;
case 5: //preis
$value = $this->app->erp->FromFormatZahlToDB($value);
if(strpos($value,','))
{
$value = str_replace(",", ".",str_replace('.','', $value));
}else{
$value = str_replace(",", ".", $value);
}
$join = "";
$preiscell = 'b.preis';
if($module == 'auftrag' || $module == 'rechnung' || $module == 'gutschrift' || $module == 'angebot' || $module == 'proformarechnung')
@ -718,12 +692,6 @@ class YUI {
if($module == 'auftrag' || $module == 'rechnung' || $module == 'angebot' || $module == 'gutschrift' || $module == 'proformarechnung')
{
$value = $this->app->erp->FromFormatZahlToDB($value);
if(strpos($value,','))
{
$value = str_replace(",", ".",str_replace('.','', $value));
}else{
$value = str_replace(",", ".", $value);
}
if($value == '')$value = '0';
$this->app->DB->Update("UPDATE $table SET rabatt='$value',keinrabatterlaubt=1 WHERE id='$id' LIMIT 1");
$result = $this->app->DB->Select("SELECT ".$this->FormatPreis('rabatt')." FROM $table WHERE id='$id' LIMIT 1");
@ -741,13 +709,6 @@ class YUI {
if($module == 'auftrag' || $module == 'rechnung' || $module == 'angebot' || $module == 'gutschrift' )
{
$value = $this->app->erp->FromFormatZahlToDB($value);
if(strpos($value,','))
{
$value = str_replace(",", ".",str_replace('.','', $value));
}else{
$value = str_replace(",", ".", $value);
}
if($value == '')$value = '0';
$this->app->DB->Update("UPDATE $table SET einkaufspreis='$value' WHERE id='$id' LIMIT 1");
$result = $this->app->DB->Select("SELECT ".$this->FormatPreis('einkaufspreis')." FROM $table WHERE id='$id' LIMIT 1");
}
@ -1552,30 +1513,22 @@ class YUI {
$module, $id, implode(', ', array_unique($positionsIds))
)
);
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs=$this->app->Container->get('FormatterService');
if(!empty($positions)) {
foreach($positions as $position) {
$positionId = $position['id'];
if(isset($idToPrice[$positionId])
&& $position['preis'] != $idToPrice[$positionId]
) {
$price = rtrim(number_format($position['preis'], 8, ',', '.'), '0');
$priceSplit = explode(',', $price);
if(strlen($priceSplit[(empty($priceSplit)?0:count($priceSplit))-1]) < 2) {
$price .= str_repeat('0',2-strlen($priceSplit[(empty($priceSplit)?0:count($priceSplit))-1]));
}
$ret[] = ['elid' => $arr[$positionId]['price_id'], 'value' => $price];
$ret[] = ['elid' => $arr[$positionId]['price_id'], 'value' => $fs->formatPreis($position['preis'])];
}
if(isset($idToQuantity[$positionId])
&& $position['menge'] != $idToQuantity[$positionId]
) {
$quantity = rtrim(number_format($position['menge'], 8, ',', ''), '0');
$quantitySplit = explode(',', $quantity);
if(isset($quantitySplit[1]) && $quantitySplit[1] === '') {
$quantity = $quantitySplit[0];
}
$ret[] = ['elid'=> $arr[$positionId]['quantity_id'], 'value' => $quantity];
$ret[] = ['elid'=> $arr[$positionId]['quantity_id'], 'value' => $fs->formatMenge($position['menge'])];
}
}
}
@ -1781,9 +1734,7 @@ class YUI {
$preis = $this->app->Secure->GetPOST("preis");
$preis = $this->app->erp->FromFormatZahlToDB($preis);
$menge = $this->app->Secure->GetPOST("menge");
//$menge = str_replace(',', '.', $menge);
$menge= $this->app->erp->FromFormatZahlToDB($menge);
if($menge < 0) $menge = 1;
$ort = $this->app->Secure->GetPOST("ort");
@ -1791,8 +1742,7 @@ class YUI {
$lieferdatum = $this->app->String->Convert($lieferdatum, "%1.%2.%3", "%3-%2-%1");
$datum = $this->app->Secure->GetPOST("datum");
$datum = $this->app->String->Convert($datum, "%1.%2.%3", "%3-%2-%1");
$rabatt = $this->app->Secure->GetPOST("rabatt");
$rabatt = str_replace(',', '.', $rabatt);
$rabatt = $this->app->erp->FromFormatZahlToDB($this->app->Secure->GetPOST("rabatt"));
if($rabatt > 0 || $rabatt=="0") $keinrabatterlaubt=1; else $keinrabatterlaubt=0;
if ($lieferdatum == "") $lieferdatum = "00.00.0000";
@ -1970,8 +1920,7 @@ class YUI {
$artikel = $this->app->Secure->GetPOST("artikel");
$stueckliste = $this->app->Secure->GetPOST("stueckliste");
$beschreibung = $this->app->Secure->GetPOST("beschreibung");
$betrag = $this->app->Secure->GetPOST("betrag");
$betrag = str_replace(',', '.', $betrag);
$betrag = $this->app->erp->FromFormatZahlToDB($this->app->Secure->GetPOST("betrag"));
$kalkulationart = $this->app->Secure->GetPOST("kalkulationart");
//$projekt = $this->app->DB->Select("SELECT projekt FROM kalkulation WHERE mitarbeiternummer='$adresse' LIMIT 1");
@ -2004,8 +1953,7 @@ class YUI {
if ($module == "reisekosten") {
$bezeichnung = $this->app->Secure->GetPOST("bezeichnung");
$betrag = $this->app->Secure->GetPOST("betrag");
$betrag = str_replace(',', '.', $betrag);
$betrag = $this->app->erp->FromFormatZahlToDB($this->app->Secure->GetPOST("betrag"));
$reisekostenart = $this->app->Secure->GetPOST("reisekostenart");
$abrechnen = $this->app->Secure->GetPOST("abrechnen");
$keineust = $this->app->Secure->GetPOST("keineust");
@ -2023,8 +1971,7 @@ class YUI {
} else
if ($module == "inventur" && $artikel_id > 0) {
$bezeichnung = $this->app->Secure->GetPOST("artikel");
$preis = $this->app->Secure->GetPOST("preis");
$preis = str_replace(',', '.', $preis);
$preis = $this->app->erp->FromFormatZahlToDB($this->app->Secure->GetPOST("preis"));
$nummer = $this->app->Secure->GetPOST("nummer");
/*adresse = $this->app->Secure->GetPOST("adresse");
@ -2046,8 +1993,7 @@ class YUI {
/*
$bezeichnung = $this->app->Secure->GetPOST("artikel");
$preis = $this->app->Secure->GetPOST("preis");
$preis = str_replace(',','.',$preis);
$preis = $this->app->erp->FromFormatZahlToDB($this->app->Secure->GetPOST("preis"));
$nummer = $this->app->Secure->GetPOST("nummer");
*/

View File

@ -1445,37 +1445,57 @@ public function NavigationHooks(&$menu)
{
return 'concat('.$spalte.",' ".$this->GetGewichtbezeichnung()."')";
}
// @refactor DbHelper Komponente
/**
* Erstelle die lokalisierten Formatierungsanweisungen für das SQL-Query.
*
* @deprecated Es wäre besser, die Formatierung in PHP zu machen
*/
function FormatPreis($spalte, $stellen = null, $punkt = false)
{
if(is_null($stellen))return "if(trim(round( $spalte *100))+0 <> trim($spalte*100)+0, format($spalte, length( trim($spalte)+0)-length(round($spalte))-1 ".($punkt?"":" ,'de_DE'")."),format($spalte,2".($punkt?"":" ,'de_DE'")."))";
return "format($spalte,$stellen".($punkt?"":" ,'de_DE'").")";
}
if (is_null($stellen)) {
return "if(trim(round( $spalte *100))+0 <> trim($spalte*100)+0, format($spalte, length( trim($spalte)+0)-length(round($spalte))-1 " . ($punkt ? "" : " ,'de_DE'") . "),format($spalte,2" . ($punkt ? "" : " ,'de_DE'") . "))";
}
return "format($spalte,$stellen" . ($punkt ? "" : " ,'de_DE'") . ")";
// Wenn die Zahlen umformatiert werden, funktioniert in den Tabellen die in Javascript implementierte Summierung nicht mehr!
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs = $this->app->Container->get('FormatterService');
$currencyFormatter = new \Xentral\Components\I18n\Formatter\CurrencyFormatter(
$punkt ? 'en_US' : $fs->getLocale(),
\Xentral\Components\I18n\Formatter\FormatterMode::MODE_NULL
);
if ($punkt) {
$currencyFormatter->hideGrouping();
}
$currencyFormatter->hideCurrency();
if ($stellen !== null) {
$currencyFormatter->setMinDigits($stellen);
}
return $currencyFormatter->formatForUserWithSqlStatement($spalte);
// if(is_null($stellen))return "if(trim(round( $spalte *100))+0 <> trim($spalte*100)+0, format($spalte, length( trim($spalte)+0)-length(round($spalte))-1 ".($punkt?"":" ,'de_DE'")."),format($spalte,2".($punkt?"":" ,'de_DE'")."))";
// return "format($spalte,$stellen".($punkt?"":" ,'de_DE'").")";
}
/**
* @deprecated
* Wandelt eine Formatierte Zahl in das Format für die Datenbank um.
*
* @param $value
*
* @return mixed
* @deprecated
*
*/
function FromFormatZahlToDB($value)
{
$poskomma = strrpos($value, ',');
$pospunkt = strrpos($value, '.');
if($poskomma === false) {
return $value;
}
if($pospunkt === false) {
return str_replace(',','.', $value);
}
if($poskomma > $pospunkt) {
return str_replace(['.', ','], ['', '.'], $value);
}
return str_replace(',','', $value);
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs = $this->app->Container->get('FormatterService');
$number = $fs->floatFromUserInput(strval($value));
return $number->getPhpVal();
}
// @refactor Formater Komponente
@ -1508,13 +1528,27 @@ public function NavigationHooks(&$menu)
}
return $prefix.'.'.'belegnr';
}
// @refactor DbHelper Komponente
/**
* Erstelle die lokalisierten Formatierungsanweisungen für das SQL-Query.
* Wird and folgenden Stellen benutzt:
* -\Artikel::TableSearch()
*
* @param $spalte
* @param $decimals
*
* @return mixed
* @deprecated Es wäre besser, die Formatierung in PHP zu machen
*
*/
function FormatMenge($spalte, $decimals = 0)
{
return ('FORMAT('.$spalte.','.$decimals.',\'de_DE\')');
// return "replace(trim($spalte)+0,'.',',')";
/** @var \Xentral\Components\I18n\FormatterService $fn */
$fs = $this->app->Container->get('FormatterService');
$number = $fs->factory(\Xentral\Components\I18n\Formatter\FloatFormatter::class);
return $number->setMinDigits($decimals)->formatForUserWithSqlStatement($spalte);
}
function FormatUCfirst($spalte)
@ -12769,12 +12803,21 @@ function SendPaypalFromAuftrag($auftrag, $test = false)
return $obj->LieferscheinCheck($lieferschein);
}
}
// @refactor Formater Komponente
/**
* Formatiert den $betrag als Währungs-Ausgabe-String.
*
* @param $betrag
*
* @return string
*/
public function EUR($betrag)
{
return number_format($betrag,2,',','.');
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs = $this->app->Container->get('FormatterService');
return $fs->formatPreis($betrag);
}
// @refactor Adresse Modul
@ -12795,36 +12838,30 @@ function SendPaypalFromAuftrag($auftrag, $test = false)
return $kreditlimit >= ($rechnungen+$auftraege);
}
// @refactor FormHelper Komponente
public function ReplaceBetrag($db,$value,$fromform = null)
/**
* Formatiert bzw. parst einen Geldbetrag für die Ausgabe im Formular oder die Speicherung in der DB.
*
* @param $db Richtung (true=Speichern in DB, false=Ausgabe im Formular)
* @param $value
* @param $fromform
*
* @return float|mixed|string
*/
public function ReplaceBetrag($db, $value, $fromform = null)
{
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs = $this->app->Container->get('FormatterService');
// wenn ziel datenbank
if($db)
{
// wenn . und , vorhanden dann entferne punkt
$pos_punkt = strrpos($value, '.');
$pos_komma = strrpos($value, ',');
if(($pos_punkt !== false) && ($pos_komma !== false)){
if($pos_punkt < $pos_komma){
$value = str_replace('.', '', $value);
}else{
$value = str_replace(',', '', $value);
}
}
return str_replace(',','.',$value);
if ($db) {
return $fs->parsePreis($value);
}
// wenn ziel formular
if ($value != "") {
//return $abkuerzung;
if($value == round((float) $value, 2)) {
return number_format((float)$value,2,',','');
}
}
return rtrim(str_replace('.',',',$value),'0');
return $fs->formatPreis($value);
}
// @refactor FormHelper Komponente
@ -13052,83 +13089,63 @@ function SendPaypalFromAuftrag($auftrag, $test = false)
}
return $value;
}
// @refactor FormHelper Komponente
function ReplaceMenge($db,$value,$fromform)
/**
* Formatiert bzw. parst eine Menge für die Ausgabe im Formular oder die Speicherung in der DB.
*
* @param $db Richtung (true=Speichern in DB, false=Ausgabe im Formular)
* @param $value
* @param $fromform
*
* @return float|mixed|string
*/
function ReplaceMenge($db, $value, $fromform)
{
$tcheck = str_replace(',','.',$value);
if($tcheck < 0) {
return 1;
}
$dbformat = 0;
if(strpos($value,'.') > 0) {
$dbformat = 1;
}
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs = $this->app->Container->get('FormatterService');
// wenn ziel datenbank
if($db)
{
if($dbformat) {
return $value;
}
if($value!=''){
return str_replace(',', '.', $value);
}
return '';
if ($db) {
return $fs->parseMenge($value);
}
// wenn ziel formular
if(strpos($value,'.') !== false)
{
$value = rtrim(rtrim($value,'0'),'.');
if($value[0] === '.') {
$value = '0'.$value;
}
}
if($dbformat) {
if($value!='') {
return str_replace('.',',',$value);
}
return '';
}
return $value;
return $fs->formatMenge($value);
}
// @refactor FormHelper Komponente
function ReplaceDecimal($db,$value,$fromform)
/**
* Formatiert bzw. parst eine Zahl für die Ausgabe im Formular oder die Speicherung in der DB.
*
* @param $db Richtung (true=Speichern in DB, false=Ausgabe im Formular)
* @param $value
* @param $fromform
*
* @return array|mixed|string|string[]
*/
function ReplaceDecimal($db, $value, $fromform)
{
//value muss hier vom format ueberprueft werden
$dbformat = 0;
if(strpos($value,'.') > 0) {
$dbformat = 1;
}
/** @var \Xentral\Components\I18n\FormatterService $fs */
$fs = $this->app->Container->get('FormatterService');
// wenn ziel datenbank
if($db)
{
if($dbformat) {
return $value;
}
if($value!=''){
return str_replace(',', '.', $value);
}
return '';
if ($db) {
$floatFormatter = $fs->floatFromUserInput(strval($value));
return $floatFormatter->getPhpVal();
}
// wenn ziel formular
if($dbformat) {
if($value!='') {
return $value;
}
return '';
if (is_numeric($value)) {
$floatFormatter = $fs->floatFromPhpVal(floatval($value));
return $floatFormatter->formatForUser();
}
return $value;
// Soweit sollte es gar nicht kommen
// TODO: soll hier eine Exception geworfen werden?
return null;
}
@ -24944,7 +24961,7 @@ function ChargenMHDAuslagern($artikel, $menge, $lagerplatztyp, $lpid,$typ,$wert,
}
$ansprechpartner = str_replace('&lt;','<',$ansprechpartner);
$ansprechpartner = str_replace('&gt;','>',$ansprechpartner);
list($name, $email) = explode('<', trim($ansprechpartner,'>'));
[$name, $email] = explode('<', trim($ansprechpartner,'>'));
$betreff = str_replace('\"','"',$betreff);
$betreff = str_replace("\'","'",$betreff);

View File

@ -22,6 +22,7 @@ include '_gen/artikel.php';
class Artikel extends GenArtikel {
/** @var Application $app */
var $app;
protected \Xentral\Components\I18n\FormatterService $formatterService;
const MODULE_NAME = 'Article';
public function TableSearch($app, $name, $erlaubtevars)
@ -938,10 +939,10 @@ class Artikel extends GenArtikel {
IF(s.art='it','<br><i style=color:#999>- Informationsteil/Dienstleistung</i>',''),IF(s.art='bt','<br><i style=color:#999>- Beistellung</i>',''), COALESCE((SELECT GROUP_CONCAT('<br><i style=color:#999>- ', art.nummer, ' ', art.name_de, ' (', alt.reason, ')', '</i>' SEPARATOR '') FROM parts_list_alternative AS alt INNER JOIN artikel AS art ON art.id = alt.alternative_article_id WHERE alt.parts_list_id = s.id), '')) as artikel,
CONCAT('<a href=\"index.php?module=artikel&action=edit&id=',a.id,'\" target=\"_blank\">',a.nummer,'</a>') as nummer,
s.referenz,
trim(s.menge)+0 as menge, a.einheit,
".$this->app->erp->FormatMenge('ifnull(lag.menge,0)').' as lager,
{$this->app->erp->FormatMenge('s.menge')} as menge, a.einheit,
{$this->app->erp->FormatMenge('ifnull(lag.menge,0)')} as lager,
CASE WHEN (SELECT SUM(lr.menge) FROM lager_reserviert lr WHERE lr.artikel=a.id) > 0
THEN (SELECT '.$this->app->erp->FormatMenge('SUM(lr.menge)')." FROM lager_reserviert lr WHERE lr.artikel=a.id)
THEN (SELECT {$this->app->erp->FormatMenge('SUM(lr.menge)')} FROM lager_reserviert lr WHERE lr.artikel=a.id)
ELSE 0
END as reserviert,
s.id as menu
@ -952,7 +953,7 @@ class Artikel extends GenArtikel {
INNER JOIN (
SELECT artikel
FROM stueckliste
WHERE stuecklistevonartikel='$id' GROUP BY artikel
WHERE stuecklistevonartikel='{$id}' GROUP BY artikel
) AS s2 ON lpi.artikel = s2.artikel
INNER JOIN lager_platz AS lp ON lpi.lager_platz = lp.id AND ifnull(lp.sperrlager,0) = 0
GROUP BY lpi.artikel) AS lag ON a.id = lag.artikel
@ -1871,6 +1872,9 @@ class Artikel extends GenArtikel {
public function __construct($app, $intern = false) {
//parent::GenArtikel($app);
$this->app=$app;
$this->formatterService = $this->app->Container->get('FormatterService');
if($intern){
return;
}
@ -6003,7 +6007,8 @@ class Artikel extends GenArtikel {
$name = 'node'.$k;
$$name = new stdClass();
$$name->id = $v['id'];
$$name->label = ' '.$v['menge'].' x <a target="_blank" href="index.php?module=artikel&action=edit&id='.$v['artikel'].'">'.$v['nummer'].' '.(strlen($v['name_de']) < 30?$v['name_de']:(mb_substr($v['name_de'],0,27).'...')).'</a>';
$$name->label = " {$this->formatterService->formatMenge($v['menge'])} x "
. '<a target="_blank" href="index.php?module=artikel&action=edit&id='.$v['artikel'].'">'.$v['nummer'].' '.(strlen($v['name_de']) < 30?$v['name_de']:(mb_substr($v['name_de'],0,27).'...')).'</a>';
$$name->checkbox = false;
$$name->inode = false;
$$name->radio = false;
@ -6035,7 +6040,8 @@ class Artikel extends GenArtikel {
$name = 'node'.$k;
$$name = new stdClass();
$$name->id = $v['id'];
$$name->label = ' '.$v['menge'].' x <a target="_blank" href="index.php?module=artikel&action=edit&id='.$v['artikel'].'">'.$v['nummer'].' '.(strlen($v['name_de']) < 30?$v['name_de']:(mb_substr($v['name_de'],0,27).'...')).'</a>';
$$name->label = " {$this->formatterService->formatMenge($v['menge'])} x "
. '<a target="_blank" href="index.php?module=artikel&action=edit&id='.$v['artikel'].'">'.$v['nummer'].' '.(strlen($v['name_de']) < 30?$v['name_de']:(mb_substr($v['name_de'],0,27).'...')).'</a>';
$$name->checkbox = false;
$$name->inode = false;
$$name->radio = false;
@ -6321,7 +6327,7 @@ class Artikel extends GenArtikel {
$id = (int)$this->app->Secure->GetPOST('id');
$data = $this->app->DB->SelectRow("SELECT s.id, s.artikel, trim(s.menge)+0 as menge, s.art, s.referenz, s.layer, s.place, s.wert, s.bauform, s.zachse, s.xpos, s.ypos FROM stueckliste s WHERE s.id = '$id' LIMIT 1");
$data = $this->app->DB->SelectRow("SELECT s.id, s.artikel, s.menge, s.art, s.referenz, s.layer, s.place, s.wert, s.bauform, s.zachse, s.xpos, s.ypos FROM stueckliste s WHERE s.id = '{$id}' LIMIT 1");
if($data){
if($data['artikel'] == 0){
@ -6349,7 +6355,8 @@ class Artikel extends GenArtikel {
}
}
}*/
$data['menge'] = $this->formatterService->formatMenge($data['menge']);
}else{
$data['id'] = 0;
@ -6378,7 +6385,7 @@ class Artikel extends GenArtikel {
$id = (int)$this->app->Secure->GetPOST('eid');
$startikelid = (int)$this->app->Secure->GetPOST('estartikelid');
$artikel = trim($this->app->Secure->GetPOST('eartikel'));
$menge = str_replace(',','.',trim($this->app->Secure->GetPOST('emenge')));
$menge = $this->formatterService->parseMenge($this->app->Secure->GetPOST('emenge'));
$art = trim($this->app->Secure->GetPOST('eart'));
//$alternative = trim($this->app->Secure->GetPOST('ealternative'));
$referenz = trim($this->app->Secure->GetPOST('ereferenz'));

View File

@ -13,6 +13,9 @@
*/
?>
<?php
use Xentral\Components\Database\Database;
class Firmendaten {
/** @var Application */
var $app;
@ -2543,57 +2546,105 @@ class Firmendaten {
}
}
}
/**
* Sprache in firmendaten_werte und user->sprachebevorzugen speichern
* @param $language
* Sprache in firmendaten_werte speichern, wenn sie geändert wurde.
* Falls der Wert in der Tabelle noch nicht existiert, wird er angelegt.
*
* @param string $newLanguage Sprache (wird in ISO 639 Alpha-3 Code umgewandelt)
*/
private function savePreferredLanguage($language){
/* THIS NEEDS TO BE REIMPLEMENTED
$lang = $this->app->erp->Firmendaten('preferredLanguage');
if($lang != $language){
$this->app->erp->FirmendatenSet('preferredLanguage',$language);
$this->app->DB->Update("UPDATE `user` SET sprachebevorzugen = '".$language."'");
private function savePreferredLanguage(string $newLanguage): void
{
$newLanguage = \Xentral\Components\I18n\Bootstrap::findLanguage(
$newLanguage
)[Xentral\Components\I18n\Iso639\Key::DEFAULT] ?? $this->getPreferredLanguage();
if ($newLanguage != ($oldLanguage = $this->app->erp->Firmendaten('preferredLanguage'))) {
if ($oldLanguage) {
$this->app->erp->FirmendatenSet('preferredLanguage', $newLanguage);
} else {
// Workaround, weil \erpAPI::AddNeuenFirmendatenWert() nicht funktioniert
/** @var Database $db */
$db = $this->app->Container->get('Database');
$insert= $db->insert()->into('firmendaten_werte')->cols(
[
'name' => 'preferredLanguage',
'typ' => 'varchar',
'typ1' => '64',
'typ2' => '',
'wert' => $newLanguage,
'default_value' => $this->getPreferredLanguage(),
'default_null' => 0,
'darf_null' => 0,
]
);
$db->perform($insert->getStatement(), $insert->getBindValues());
/*
$this->app->erp->AddNeuenFirmendatenWert(
'preferredLanguage',
'varchar',
'64',
'',
$newLanguage,
$this->getPreferredLanguage(),
0,
0
);
*/
}
}
*/
}
/**
* Bevorzugte Sprache aus firmendaten_werte
* @return string Sprache
* Bevorzugte Sprache aus firmendaten_werte zurückgeben.
* Wenn die Sprache nicht gesetzt ist, die Default-Sprache zurückgeben.
*
* @return string Sprache als ISO 639 Alpha-3 Code
*/
private function getPreferredLanguage(){
$lang = $this->app->erp->Firmendaten('preferredLanguage');
if(!empty($lang)) {
return $lang;
}
// $this->app->erp->AddNeuenFirmendatenWert('preferredLanguage','varchar','64','','deutsch','deutsch',0,0);
return 'deutsch';
private function getPreferredLanguage(): string
{
/** @var \Xentral\Components\I18n\Localization $localization */
$localization = $this->app->Container->get('Localization');
return \Xentral\Components\I18n\Bootstrap::findLanguage(
$this->app->erp->Firmendaten('preferredLanguage') ?? $localization->getLanguage()
)[Xentral\Components\I18n\Iso639\Key::DEFAULT];
}
/**
* Liefert einen String aus HTML-Optionen zurück
* @param string $select Wert aus der Datenbank
* Liefert einen String aus HTML-Optionen zurück.
*
* @param string $select Gewählter Wert
*
* @return string
*/
private function languageSelectOptions($select='deutsch'){
private function languageSelectOptions(string $select)
{
$select=\Xentral\Components\I18n\Bootstrap::findLanguage($select)[Xentral\Components\I18n\Iso639\Key::DEFAULT];
$out = '';
$sprachen = $this->getLanguages();
foreach($sprachen as $sprache) {
$selected = (($select==$sprache) ? 'selected' : '');
$out .= "<option value=\"$sprache\" $selected>$sprache</option>";
foreach ($this->getLanguages() as $sprache) {
if($language=\Xentral\Components\I18n\Bootstrap::findLanguage($sprache)) {
$selected = (($select == $language[Xentral\Components\I18n\Iso639\Key::DEFAULT]) ? ' selected="selected"' : '');
$out .= "<option value=\"{$language[Xentral\Components\I18n\Iso639\Key::DEFAULT]}\"{$selected}>{$language[Xentral\Components\I18n\Iso639\Key::NAME_deu]}</option>";
}
}
return $out;
}
/**
* Liefert einen Array aus Strings zurück. Immer mindestens 'deutsch' enthalten
* Liefert einen Array aus Strings zurück. Immer mindestens 'deutsch' enthalten.
*
* @return array
* @todo Sollte eventuell zusammengelegt oder in den Übersetzer verschoben werden.
* @see \Firmendaten::getLanguages()
* @deprecated
*/
private function getLanguages(){

View File

@ -2819,7 +2819,19 @@ $this->app->Tpl->Add('TODOFORUSER',"<tr><td width=\"90%\">".$tmp[$i]['aufgabe'].
header('Location: '.$_SERVER['HTTP_REFERER']);
exit;
}
/**
* Diese Funktion holt die Sprache von den Firmendaten, falls keine Sprache in $fromPost übergeben wurde.
* Sie wurde nur verwendet, um eine Vorgabe im sprachebevorzugen-SELECT beim Benutzer zu erzeugen.
* Das wird jetzt anders gelöst.
*
* @param $fromPost
*
* @return array|mixed|string|null
* @deprecated Nicht mehr benötigt
*/
private function getCurrentDefaultLanguage($fromPost){
if(empty($fromPost)){
@ -2831,29 +2843,43 @@ $this->app->Tpl->Add('TODOFORUSER',"<tr><td width=\"90%\">".$tmp[$i]['aufgabe'].
}
return $fromPost;
}
/**
* Liefert einen String aus HTML-Optionen zurück
* @param string $fromPost
* Liefert einen String aus HTML-Select-Optionen zurück für die Sprachauswahl beim Benutzer.
*
* @param string|null $userPreferredLanguage Gewählte Sprache von den Usereinstellungen
*
* @return string
*/
private function languageSelectOptions($fromPost=''){
$select = $this->getCurrentDefaultLanguage($fromPost);
$out = "";
$sprachen = $this->getLanguages();
foreach($sprachen as $sprache) {
$selected = (($select==$sprache) ? 'selected' : '');
$out .= "<option value=\"$sprache\" $selected>$sprache</option>";
private function languageSelectOptions(string|null $userPreferredLanguage='') {
$select=\Xentral\Components\I18n\Bootstrap::findLanguage(strval($userPreferredLanguage))[Xentral\Components\I18n\Iso639\Key::DEFAULT];
if(empty($select)) {
/** @var \Xentral\Components\I18n\Localization $localization */
$localization=$this->app->Container->get('Localization');
$select=$localization->getLanguage();
}
$out = '';
foreach ($this->getLanguages() as $sprache) {
if($language=\Xentral\Components\I18n\Bootstrap::findLanguage($sprache)) {
$selected = (($select == $language[Xentral\Components\I18n\Iso639\Key::DEFAULT]) ? ' selected="selected"' : '');
$out .= "<option value=\"{$language[Xentral\Components\I18n\Iso639\Key::DEFAULT]}\"{$selected}>{$language[Xentral\Components\I18n\Iso639\Key::NAME_deu]}</option>";
}
}
return $out;
}
/**
* Liefert einen Array aus Strings zurück. Immer mindestens 'deutsch' enthalten
* Liefert einen Array aus Strings zurück. Immer mindestens 'deutsch' enthalten.
*
* @return array
* @todo Sollte eventuell zusammengelegt oder in den Übersetzer verschoben werden.
* @see \Firmendaten::getLanguages()
* @deprecated
*/
private function getLanguages(){

View File

@ -20,10 +20,12 @@ class WidgetGenadresse
private $app; //application object
public $form; //store form object
protected $parsetarget; //target for content
protected \Xentral\Components\I18n\FormatterService $formatterService;
public function __construct($app,$parsetarget)
{
$this->app = $app;
$this->formatterService = $this->app->Container->get('FormatterService');
$this->parsetarget = $parsetarget;
$this->Form();
}

View File

@ -28,17 +28,21 @@ class WidgetAdresse extends WidgetGenAdresse
$this->form->ReplaceFunction("mandatsreferenzdatum",$this,"ReplaceDatum");
$this->form->ReplaceFunction("liefersperredatum",$this,"ReplaceDatum");
$this->form->ReplaceFunction("arbeitszeitprowoche",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("zahlungszielskonto",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("zahlungszielskontolieferant",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("provision",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("portofreiab",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("portofreiablieferant",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("kreditlimit",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("kreditlimiteinmalig",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("arbeitszeitprowoche", $this->formatterService, "replaceDecimalOrEmpty");
$this->form->ReplaceFunction("zahlungszieltage", $this->formatterService, "replaceIntegerOrEmpty");
$this->form->ReplaceFunction("zahlungszieltagelieferant", $this->formatterService, "replaceIntegerOrEmpty");
$this->form->ReplaceFunction("zahlungszieltageskonto", $this->formatterService, "replaceDecimalOrEmpty");
$this->form->ReplaceFunction("zahlungszieltageskontolieferant", $this->formatterService, "replaceDecimalOrEmpty");
$this->form->ReplaceFunction("zahlungszielskonto", $this->formatterService, "replaceDecimalPercentOrEmpty");
$this->form->ReplaceFunction("zahlungszielskontolieferant", $this->formatterService, "replaceDecimalPercentOrEmpty");
$this->form->ReplaceFunction("provision", $this->formatterService, "replaceDecimalPercentOrEmpty");
$this->form->ReplaceFunction("portofreiab", $this->formatterService, "replaceCurrencyOrEmpty");
$this->form->ReplaceFunction("portofreiablieferant", $this->formatterService, "replaceCurrencyOrEmpty");
$this->form->ReplaceFunction("kreditlimit", $this->formatterService, "replaceCurrencyOrEmpty");
$this->form->ReplaceFunction("kreditlimiteinmalig", $this->formatterService, "replaceCurrencyOrEmpty");
$this->form->ReplaceFunction("lat",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("lng",$this,"ReplaceBetrag");
$this->form->ReplaceFunction("lat", $this->formatterService, "replaceDecimalGeoOrEmpty");
$this->form->ReplaceFunction("lng", $this->formatterService, "replaceDecimalGeoOrEmpty");
$this->form->ReplaceFunction("name",$this,"ReplaceTrim");
$this->app->YUI->CkEditor("sonstiges","internal");