Merge e438393e7a into 74aeb90758
This commit is contained in:
commit
124c243a12
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Formatter;
|
||||
|
||||
use Vtiful\Kernel\Format;
|
||||
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||
|
||||
/**
|
||||
* AbstractFormatter.
|
||||
*
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class AbstractFormatter implements FormatterInterface
|
||||
{
|
||||
private string $locale;
|
||||
private FormatterMode $strictness;
|
||||
private mixed $parsedValue;
|
||||
|
||||
|
||||
|
||||
public function __construct(string $locale, FormatterMode $strictness = FormatterMode::MODE_STRICT)
|
||||
{
|
||||
$this->locale = $locale;
|
||||
$this->strictness = $strictness;
|
||||
$this->init();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize the formatter. Overload this instead of the constructor.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
protected function init(): void
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the native PHP value in the formatter.
|
||||
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
protected function setParsedValue($value): self
|
||||
{
|
||||
$this->parsedValue = $value;
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the native PHP value in the formatter.
|
||||
* The value must ALWAYS be of the requested type (or NULL or '' depending on the strictness).
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPhpVal(mixed $input): self
|
||||
{
|
||||
if ($this->isStrictValidPhpVal($input)
|
||||
|| $this->isEmptyValidPhpValue($input)
|
||||
|| $this->isNullValidPhpValue($input)) {
|
||||
$this->parsedValue = $input;
|
||||
return $this;
|
||||
} else {
|
||||
throw new TypeErrorException(
|
||||
"Value " . var_export($input, true) . " is not a valid type for " . get_class(
|
||||
$this
|
||||
) . " with strictness {$this->getStrictness()->name}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the native PHP value from the formatter.
|
||||
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPhpVal(): mixed
|
||||
{
|
||||
return $this->parsedValue;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the locale used for output formatting.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function getLocale(): string
|
||||
{
|
||||
return $this->locale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the current strictness mode.
|
||||
*
|
||||
* @return FormatterMode
|
||||
* @see FormatterMode
|
||||
*
|
||||
*/
|
||||
public function getStrictness(): FormatterMode
|
||||
{
|
||||
return $this->strictness;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if $input conforms to the MODE_NULL strictness AND strictness is set.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isNullValidPhpValue(mixed $input): bool
|
||||
{
|
||||
return ($this->getStrictness() == FormatterMode::MODE_NULL) && ($input === null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if $input conforms to the MODE_EMPTY strictness AND strictness is set.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
protected function isEmptyValidPhpValue(mixed $input): bool
|
||||
{
|
||||
return ($this->getStrictness() == FormatterMode::MODE_EMPTY) && is_string($input) && (trim($input) === '');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Clean up input string.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
protected function sanitizeInputString(string $string): string
|
||||
{
|
||||
return trim($string);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,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);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Formatter\Exception;
|
||||
|
||||
class TypeErrorException extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,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);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Formatter;
|
||||
|
||||
/**
|
||||
* FormatterInterface defines the mandatory interface each formatter has to provide.
|
||||
*
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
interface FormatterInterface
|
||||
{
|
||||
/**
|
||||
* Parse string from user input and store as desired type in object.
|
||||
* If parsing fails, an Exception is thrown.
|
||||
*
|
||||
* @param string $input
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function parseUserInput(string $input): self;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the native PHP value in the formatter.
|
||||
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return self
|
||||
*/
|
||||
public function setPhpVal(mixed $input): self;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Get the native PHP value from the formatter.
|
||||
* The value must ALWAYS be of the requested type or an Exception is thrown.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getPhpVal(): mixed;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a string representing the PHP value as a formatted value.
|
||||
* Throws an Exception if no value was set before or the value is of the wrong type.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formatForUser(): string;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a string that can be used in an SQL query to format the value for presentation to a User.
|
||||
* Should return the same string as if it was formatted by FormatterInterface::formatForUser(), but directly from
|
||||
* the database.
|
||||
* This function does not need a native PHP value, but a table column is needed.
|
||||
*
|
||||
* @param string $col
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function formatForUserWithSqlStatement(string $col): string;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Test $input for the correct (strict) type the class supports. Return false otherwise.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isStrictValidPhpVal($input): bool;
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Formatter;
|
||||
|
||||
enum FormatterMode
|
||||
{
|
||||
|
||||
/**
|
||||
* Only values representing the class type are allowed for input and output. This means, you can only store a
|
||||
* float (or it's localized string representation) to a FloatFormatter).
|
||||
*/
|
||||
case MODE_STRICT;
|
||||
|
||||
/**
|
||||
* Allow NULL as valid value in addition to the formatter type. If the user enters an empty string, this results
|
||||
* in a PHP value of NULL and vice versa.
|
||||
*/
|
||||
case MODE_NULL;
|
||||
|
||||
/**
|
||||
* Allow an empty string in addition to the formatter type. If the user entern an empty string, this results in
|
||||
* an emtpy string as PHP value and vice versa.
|
||||
*/
|
||||
case MODE_EMPTY;
|
||||
}
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Formatter;
|
||||
|
||||
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||
|
||||
class IntegerFormatter extends FloatFormatter
|
||||
{
|
||||
|
||||
|
||||
protected function init(): void
|
||||
{
|
||||
$this->parseType = \NumberFormatter::TYPE_INT64;
|
||||
parent::init();
|
||||
parent::setMaxDigits(0);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* For IntegerFormatter, strip decimals from $input if a number is given.
|
||||
*
|
||||
* @param mixed $input
|
||||
*
|
||||
* @return AbstractFormatter
|
||||
*/
|
||||
public function setPhpVal(mixed $input): AbstractFormatter
|
||||
{
|
||||
return parent::setPhpVal(is_numeric($input) ? intval($input) : $input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if $input is an integer.
|
||||
*
|
||||
* @param $input
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isStrictValidPhpVal($input): bool
|
||||
{
|
||||
return is_integer($input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Don't allow setting of min digits.
|
||||
*
|
||||
* @param int $digits
|
||||
*
|
||||
* @return \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||
*/
|
||||
public function setMinDigits(int $digits): \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Don't allow setting of max digits.
|
||||
*
|
||||
* @param int $digits
|
||||
*
|
||||
* @return \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||
*/
|
||||
|
||||
public function setMaxDigits(int $digits): \Xentral\Components\I18n\Formatter\FloatFormatter
|
||||
{
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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']);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Test;
|
||||
|
||||
require(__DIR__ . '/../../../bootstrap.php');
|
||||
|
||||
use Xentral\Components\I18n\Formatter\CurrencyFormatter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Xentral\Components\I18n\Formatter\FormatterMode;
|
||||
|
||||
class CurrencyFormatterTest extends TestCase
|
||||
{
|
||||
public function testStrictModeWithValue()
|
||||
{
|
||||
$floatFormatter = new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234,56 EUR', $output);
|
||||
|
||||
$floatFormatter = new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234 EUR', $output);
|
||||
|
||||
$floatFormatter = new CurrencyFormatter('de_CH', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('CHF 1’234.56', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithValueWithoutCCY()
|
||||
{
|
||||
$floatFormatter = new CurrencyFormatter('de_CH', FormatterMode::MODE_STRICT);
|
||||
$floatFormatter->hideCurrency();
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1’234.56', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->parseUserInput('1234,56 EUR')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234.56, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('EUR 1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithValueInputWithoutCCY()
|
||||
{
|
||||
$floatFormatter = (new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT))->hideCurrency();
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234.56, $output);
|
||||
|
||||
$floatFormatter = (new CurrencyFormatter('de_DE', FormatterMode::MODE_STRICT))->hideCurrency();
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testCanParseOwnOutput()
|
||||
{
|
||||
$value = 1234567.89;
|
||||
$locale = 'de_DE';
|
||||
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
|
||||
$locale = 'de_CH';
|
||||
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
|
||||
$locale = 'de_AT';
|
||||
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testCanParseOwnOutputWithoutCCY()
|
||||
{
|
||||
$value = 1234567.89;
|
||||
$locale = 'de_DE';
|
||||
$floatFormatter1 = new CurrencyFormatter($locale);
|
||||
$floatFormatter1->hideCurrency();
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||
$floatFormatter2->hideCurrency();
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
|
||||
$locale = 'de_CH';
|
||||
$floatFormatter1 = (new CurrencyFormatter($locale))->hideCurrency();
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new CurrencyFormatter($locale);
|
||||
$floatFormatter2->hideCurrency();
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
|
||||
$locale = 'de_AT';
|
||||
$floatFormatter1 = (new CurrencyFormatter($locale))->hideCurrency();
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
$floatFormatter1->hideCurrency();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = (new CurrencyFormatter($locale))->hideCurrency();
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,307 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Test;
|
||||
|
||||
require(__DIR__ . '/../../../bootstrap.php');
|
||||
|
||||
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
use Xentral\Components\I18n\Formatter\FormatterMode;
|
||||
|
||||
class FloatFormatterTest extends TestCase
|
||||
{
|
||||
public function testStrictModeWithValue()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234,56', $output);
|
||||
|
||||
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234.56, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithValueInputNoDecimals()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithNull()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithNullInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithEmpty()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testStrictModeWithEmptyInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testNullModeWithValue()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234,56', $output);
|
||||
|
||||
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testNullModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234.56, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testNullModeWithNull()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testNullModeWithNullInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertNull($output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testNullModeWithEmpty()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testNullModeWithEmptyInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertNull($output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testEmptyModeWithValue()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->setPhpVal(1234.56)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234,56', $output);
|
||||
|
||||
$output = $floatFormatter->setPhpVal(1234)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testEmptyModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234.56, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsFloat($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testEmptyModeWithNull()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testEmptyModeWithNullInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testEmptyModeWithEmpty()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testEmptyModeWithEmptyInput()
|
||||
{
|
||||
$floatFormatter = new FloatFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testCanParseOwnOutput()
|
||||
{
|
||||
$value = 1234567.89;
|
||||
$locale = 'de_DE';
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new FloatFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
|
||||
$locale = 'de_CH';
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new FloatFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
|
||||
$locale = 'de_AT';
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new FloatFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals($value, $input);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testCanSetDigits()
|
||||
{
|
||||
$value = 1234567.8901234;
|
||||
$locale = 'de_DE';
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(4)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.567,8901', $output);
|
||||
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(3)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.567,89', $output);
|
||||
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(3)->setMinDigits(3)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.567,890', $output);
|
||||
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMinDigits(10)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.567,8901234000', $output);
|
||||
|
||||
$floatFormatter1 = new FloatFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(0)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.568', $output);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,144 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Test;
|
||||
|
||||
require(__DIR__ . '/../../../bootstrap.php');
|
||||
|
||||
|
||||
use Xentral\Components\I18n\Formatter\FloatFormatter;
|
||||
use Xentral\Components\I18n\FormatterService;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class FormatterServiceTest extends TestCase
|
||||
{
|
||||
public function testCanCreateFormatterService()
|
||||
{
|
||||
$formatterService = new FormatterService('de_DE');
|
||||
$this->assertInstanceOf(FormatterService::class, $formatterService);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testFloatFromUserInput()
|
||||
{
|
||||
$formatterService = new FormatterService('de_DE');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1.234,56");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234.56, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_DE');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1234,56");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234.56, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_DE');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1.234.567,89");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234567.89, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_DE');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1234567,89");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234567.89, $phpVal);
|
||||
|
||||
|
||||
$formatterService = new FormatterService('de_CH');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1'234.56");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234.56, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_CH');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1234.56");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234.56, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_CH');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1'234'567.89");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234567.89, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_CH');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1234567.89");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234567.89, $phpVal);
|
||||
|
||||
|
||||
$formatterService = new FormatterService('de_AT');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1 234,56");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234.56, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_AT');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1234,56");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234.56, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_AT');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1 234 567,89");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234567.89, $phpVal);
|
||||
|
||||
$formatterService = new FormatterService('de_AT');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromUserInput("1234567,89");
|
||||
$phpVal = $floatFormatter->getPhpVal();
|
||||
$this->assertIsFloat($phpVal);
|
||||
$this->assertEquals(1234567.89, $phpVal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function testFloatFromPhpVal()
|
||||
{
|
||||
$formatterService = new FormatterService('de_DE');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromPhpVal(1234567.89);
|
||||
$formattedString = $floatFormatter->formatForUser();
|
||||
$this->assertIsString($formattedString);
|
||||
$this->assertEquals("1.234.567,89", $formattedString);
|
||||
|
||||
|
||||
$formatterService = new FormatterService('de_CH');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromPhpVal(1234567.89);
|
||||
$formattedString = $floatFormatter->formatForUser();
|
||||
$this->assertIsString($formattedString);
|
||||
$this->assertEquals("1’234’567.89", $formattedString);
|
||||
|
||||
|
||||
$formatterService = new FormatterService('de_AT');
|
||||
/** @var FloatFormatter $floatFormatter */
|
||||
$floatFormatter = $formatterService->floatFromPhpVal(1234567.89);
|
||||
$formattedString = $floatFormatter->formatForUser();
|
||||
$this->assertIsString($formattedString);
|
||||
$this->assertEquals("1 234 567,89", $formattedString);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,247 @@
|
|||
<?php
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023 Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* SPDX-License-Identifier: AGPL-3.0-only
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Xentral\Components\I18n\Test;
|
||||
|
||||
require(__DIR__ . '/../../../bootstrap.php');
|
||||
|
||||
use Xentral\Components\I18n\Formatter\Exception\TypeErrorException;
|
||||
use Xentral\Components\I18n\Formatter\FormatterMode;
|
||||
use Xentral\Components\I18n\Formatter\IntegerFormatter;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
|
||||
class IntegerFormatterTest extends TestCase
|
||||
{
|
||||
public function testStrictModeWithValue()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
|
||||
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
|
||||
}
|
||||
|
||||
public function testStrictModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsInt($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsInt($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
|
||||
}
|
||||
|
||||
public function testStrictModeWithNull()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||
}
|
||||
public function testStrictModeWithNullInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
}
|
||||
public function testStrictModeWithEmpty()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||
}
|
||||
public function testStrictModeWithEmptyInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_STRICT);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
}
|
||||
public function testNullModeWithValue()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->setPhpVal(floatval(1234.56))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
|
||||
$output = $floatFormatter->setPhpVal(intval(1234))->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
}
|
||||
|
||||
public function testNullModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsInt($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsInt($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
|
||||
public function testNullModeWithNull()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
public function testNullModeWithNullInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertNull($output);
|
||||
}
|
||||
public function testNullModeWithEmpty()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||
}
|
||||
public function testNullModeWithEmptyInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_NULL);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertNull($output);
|
||||
}
|
||||
public function testEmptyModeWithValue()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->setPhpVal(1234.56)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
|
||||
$output = $floatFormatter->setPhpVal(1234)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('1.234', $output);
|
||||
}
|
||||
public function testEmptyModeWithValueInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->parseUserInput('1234,56')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsInt($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
|
||||
$output = $floatFormatter->parseUserInput('1234')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsInt($output);
|
||||
$this->assertEquals(1234, $output);
|
||||
}
|
||||
public function testEmptyModeWithNull()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$this->expectException(TypeErrorException::class);
|
||||
$output = $floatFormatter->setPhpVal(null)->formatForUser();
|
||||
}
|
||||
public function testEmptyModeWithNullInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
public function testEmptyModeWithEmpty()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->setPhpVal('')->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
public function testEmptyModeWithEmptyInput()
|
||||
{
|
||||
$floatFormatter = new IntegerFormatter('de_DE', FormatterMode::MODE_EMPTY);
|
||||
$output = $floatFormatter->parseUserInput('')->getPhpVal();
|
||||
var_dump($output);
|
||||
$this->assertIsString($output);
|
||||
$this->assertEquals('', $output);
|
||||
}
|
||||
public function testCanParseOwnOutput()
|
||||
{
|
||||
$value = 1234567.89;
|
||||
$locale = 'de_DE';
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new IntegerFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals(intval($value), $input);
|
||||
|
||||
$locale = 'de_CH';
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new IntegerFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals(intval($value), $input);
|
||||
|
||||
$locale = 'de_AT';
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->formatForUser();
|
||||
var_dump($output);
|
||||
$floatFormatter2 = new IntegerFormatter($locale);
|
||||
$input = $floatFormatter2->parseUserInput($output)->getPhpVal();
|
||||
var_dump($input);
|
||||
$this->assertEquals(intval($value), $input);
|
||||
}
|
||||
|
||||
public function testCanSetDigits()
|
||||
{
|
||||
$value = 1234567.8901234;
|
||||
$locale = 'de_DE';
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMinIntDigits(10)->setMaxDigits(4)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('0.001.234.567', $output);
|
||||
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxIntDigits(4)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('4.567', $output);
|
||||
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxDigits(3)->setMinDigits(3)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.567', $output);
|
||||
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMaxSignificantDigits(3)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.230.000', $output);
|
||||
|
||||
$floatFormatter1 = new IntegerFormatter($locale);
|
||||
$output = $floatFormatter1->setPhpVal($value)->setMinSignificantDigits(3)->formatForUser();
|
||||
var_dump($output);
|
||||
$this->assertEquals('1.234.567', $output);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -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
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
*/
|
||||
|
||||
|
|
|
|||
|
|
@ -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('<','<',$ansprechpartner);
|
||||
$ansprechpartner = str_replace('>','>',$ansprechpartner);
|
||||
list($name, $email) = explode('<', trim($ansprechpartner,'>'));
|
||||
[$name, $email] = explode('<', trim($ansprechpartner,'>'));
|
||||
|
||||
$betreff = str_replace('\"','"',$betreff);
|
||||
$betreff = str_replace("\'","'",$betreff);
|
||||
|
|
|
|||
|
|
@ -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'));
|
||||
|
|
|
|||
|
|
@ -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(){
|
||||
|
||||
|
|
|
|||
|
|
@ -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(){
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue