Compare commits
6
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
74aeb90758 | ||
|
|
7c4c9e64d6 | ||
|
|
6695369af7 | ||
|
|
fdafc13e2c | ||
|
|
bd0392698d | ||
|
|
dc58045423 |
@@ -0,0 +1,151 @@
|
||||
<?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\Database\Database;
|
||||
use Xentral\Components\Http\Request;
|
||||
use Xentral\Components\Http\Session\Session;
|
||||
use Xentral\Core\DependencyInjection\ServiceContainer;
|
||||
|
||||
/**
|
||||
* Factory for localization object.
|
||||
*
|
||||
* @see Localization
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
final class Bootstrap
|
||||
{
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public static function registerServices(): array
|
||||
{
|
||||
return [
|
||||
'Localization' => 'onInitLocalization',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Replaces umlauts with their 2 character representation.
|
||||
*
|
||||
* @param string $string
|
||||
*
|
||||
* @return array|string|string[]
|
||||
*/
|
||||
public static function replaceUmlauts(string $string)
|
||||
{
|
||||
$search = ['ä', 'ö', 'ü', 'Ä', 'Ö', 'Ü', 'ß'];
|
||||
$replace = ['ae', 'oe', 'ue', 'Ae', 'Oe', 'Ue', 'ss'];
|
||||
return str_replace($search, $replace, $string);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the language information from the given string.
|
||||
*
|
||||
* @param string $lang
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public static function findLanguage(string $lang): ?array
|
||||
{
|
||||
$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 $val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the region information from the given string.
|
||||
*
|
||||
* @param string $region
|
||||
*
|
||||
* @return array|null
|
||||
*/
|
||||
public static function findRegion(string $region): ?array
|
||||
{
|
||||
$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 $val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This is the factory for the Localization object.
|
||||
*
|
||||
* @param ServiceContainer $container
|
||||
*
|
||||
* @return Localization
|
||||
*/
|
||||
public static function onInitLocalization(ServiceContainer $container): Localization
|
||||
{
|
||||
/** @var Request $request */
|
||||
$request = $container->get('Request');
|
||||
/** @var Session $session */
|
||||
$session = $container->get('Session');
|
||||
/** @var \erpooSystem $app */
|
||||
$app = $container->get('LegacyApplication');
|
||||
/** @var Database $db */
|
||||
$db = $container->get('Database');
|
||||
|
||||
$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'))) {
|
||||
$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')))) {
|
||||
$config[Localization::LOCALE_DEFAULT] = "{$firmaLang[Iso639\Key::ALPHA_2]}_{$firmaRegion[Iso3166\Key::ALPHA_2]}";
|
||||
}
|
||||
|
||||
|
||||
// Get User
|
||||
$usersettings = [];
|
||||
if ($user = $app->User) {
|
||||
// Get User's address from user
|
||||
$userAddress = $db->fetchRow(
|
||||
$db->select()->cols(['*'])->from('adresse')->where('id=:id'),
|
||||
['id' => $user->GetAdresse()]
|
||||
);
|
||||
|
||||
// Get language from user account and normalize to 3-letter-code and 2-letter-code
|
||||
if ($userLang = self::findLanguage($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']))) {
|
||||
$usersettings['locale'] = "{$userLang[Iso639\Key::ALPHA_2]}_{$userRegion[Iso3166\Key::ALPHA_2]}";
|
||||
}
|
||||
}
|
||||
|
||||
// Create Localization object
|
||||
return new Localization($request, $session, $usersettings, $config);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
/**
|
||||
* Provides array access functions to the data provider.
|
||||
*
|
||||
* @see \ArrayAccess
|
||||
* @see DataProvider
|
||||
* @see DataProviderInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
trait ArrayAccessTrait
|
||||
{
|
||||
/**
|
||||
* Whether an offset exists.
|
||||
*
|
||||
* @param string $offset
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function offsetExists($offset): bool
|
||||
{
|
||||
return array_key_exists($offset, $this->DataProvider_DATA);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Offset to retrieve.
|
||||
*
|
||||
* @param string $offset
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function offsetGet($offset): array
|
||||
{
|
||||
return $this->DataProvider_DATA[$offset];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Assign a value to the specified offset.
|
||||
* No function since data set is read only.
|
||||
*
|
||||
* @param string $offset
|
||||
* @param array $value
|
||||
*/
|
||||
public function offsetSet($offset, $value)
|
||||
{
|
||||
// $this->DataProvider_DATA[$offset]=$value;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Unset an offset.
|
||||
* No function since data set is read only.
|
||||
*
|
||||
* @param string $offset
|
||||
*/
|
||||
public function offsetUnset($offset)
|
||||
{
|
||||
// unset($this->DataProvider_DATA[$offset]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
/**
|
||||
* Provides countable functions to the data provider.
|
||||
*
|
||||
* @see \Countable
|
||||
* @see DataProvider
|
||||
* @see DataProviderInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
trait CountableTrait
|
||||
{
|
||||
/**
|
||||
* Counts the number of records in the private $data array.
|
||||
*
|
||||
* @return int Number of records
|
||||
*/
|
||||
public function count(): int
|
||||
{
|
||||
return count($this->DataProvider_DATA);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
|
||||
/**
|
||||
* Abstract filter class.
|
||||
*
|
||||
* @see DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Pointer to next filter in chain.
|
||||
*
|
||||
* @var DataFilterInterface
|
||||
*/
|
||||
private $nextFilter = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::then()
|
||||
*/
|
||||
public function then(DataFilterInterface $filter): DataFilterInterface
|
||||
{
|
||||
if (!$this->nextFilter) {
|
||||
$this->nextFilter = $filter;
|
||||
} else {
|
||||
$this->nextFilter->then($filter);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Applies the filter to the data and executes the next filter
|
||||
* if present.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::__invoke()
|
||||
*/
|
||||
public function __invoke(array $data): array
|
||||
{
|
||||
// echo get_called_class()."::__invoke(\$data)".PHP_EOL;
|
||||
|
||||
$filteredData = [];
|
||||
foreach ($data as $key => $val) {
|
||||
if ($this->selectItem($key, $val)) {
|
||||
$filteredData[$key] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->nextFilter) {
|
||||
$filteredData = ($this->nextFilter)($filteredData);
|
||||
}
|
||||
return $filteredData;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check if the current item is to be selected for
|
||||
* the dataset.
|
||||
*
|
||||
* @param mixed $key
|
||||
* @param mixed $val
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
abstract protected function selectItem(&$key, &$val): bool;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
|
||||
/**
|
||||
* Filter Interface.
|
||||
*
|
||||
* @see DataFilter
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
interface DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Add a filter to the end of the filter chain.
|
||||
*
|
||||
* @param DataFilterInterface $filter Filter to add
|
||||
*
|
||||
* @return DataFilterInterface Start of filter chain
|
||||
*/
|
||||
function then(DataFilterInterface $filter): DataFilterInterface;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Applies the filter to the data and executes the next filter
|
||||
* if present.
|
||||
*
|
||||
* @see \Ruga\I18n\Dataaccess\DataFilterInterface::__invoke()
|
||||
*/
|
||||
function __invoke(array $data): array;
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
use ArrayAccess;
|
||||
use Countable;
|
||||
use Iterator;
|
||||
|
||||
/**
|
||||
* Abstract implementation of a general data provider.
|
||||
*
|
||||
* @see DataProviderInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class DataProvider implements Countable, Iterator, ArrayAccess, DataProviderInterface
|
||||
{
|
||||
use CountableTrait;
|
||||
use IteratorTrait;
|
||||
use ArrayAccessTrait;
|
||||
|
||||
|
||||
/**
|
||||
* Holds filtered data.
|
||||
*
|
||||
* @var mixed
|
||||
*/
|
||||
private $DataProvider_DATA = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Create the object and apply data filter.
|
||||
*
|
||||
* @param DataFilterInterface|null $filter
|
||||
*/
|
||||
public function __construct(DataFilterInterface $filter = null)
|
||||
{
|
||||
if ($filter) {
|
||||
$this->DataProvider_DATA = $filter($this->getOriginalData());
|
||||
} else {
|
||||
$this->DataProvider_DATA = $this->getOriginalData();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the original data array).
|
||||
* Raw data before any filtering takes place.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
abstract protected function getOriginalData(): array;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array suitable for select fields.
|
||||
* The key of the filtered data set is used as key of the
|
||||
* array and $desiredName field is used as value.
|
||||
*
|
||||
* @param string $desiredName
|
||||
*
|
||||
* @return array;
|
||||
*/
|
||||
public function getMultiOptions($desiredName = 'NAME_deu'): array
|
||||
{
|
||||
$a = [];
|
||||
foreach ($this as $key => $l) {
|
||||
$a[$key] = $l[$desiredName];
|
||||
}
|
||||
return $a;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the field $desiredName from the record $id.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param string $desiredName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getString($id, $desiredName): string
|
||||
{
|
||||
if (!isset($this[$id])) {
|
||||
throw new Exception\OutOfRangeException("Index '{$id}' not found");
|
||||
}
|
||||
$d = $this[$id];
|
||||
if ($desiredName) {
|
||||
if ($desiredName == 'POST') {
|
||||
return strtoupper($this->getString($id, 'NAME_eng'));
|
||||
}
|
||||
return $d[$desiredName];
|
||||
}
|
||||
throw new Exception\OutOfRangeException("No '{$desiredName}' data for '{$id}'");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the item at position $id.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData($id)
|
||||
{
|
||||
if (empty($id)) {
|
||||
return null;
|
||||
}
|
||||
if (!isset($this[$id])) {
|
||||
throw new Exception\OutOfRangeException("Index '{$id}' not found.");
|
||||
}
|
||||
return $this[$id];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
|
||||
/**
|
||||
* Interface to the general data provider class.
|
||||
*
|
||||
* @see DataProvider
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
interface DataProviderInterface
|
||||
{
|
||||
/**
|
||||
* Returns an array suitable for select fields.
|
||||
* The key of the filtered data set is used as key of the
|
||||
* array and $desiredName field is used as value.
|
||||
*
|
||||
* @param string $desiredName
|
||||
*
|
||||
* @return array;
|
||||
*/
|
||||
public function getMultiOptions($desiredName): array;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the field $desiredName from the record $id.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param string $desiredName
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getString($id, $desiredName): string;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the item at position $id.
|
||||
*
|
||||
* @param string $id
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function getData($id);
|
||||
}
|
||||
@@ -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\Dataaccess\Exception;
|
||||
|
||||
class OutOfRangeException extends \OutOfRangeException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
<?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\Dataaccess;
|
||||
|
||||
/**
|
||||
* Provides iterator functions to the data provider.
|
||||
*
|
||||
* @see \Iterator
|
||||
* @see DataProvider
|
||||
* @see DataProviderInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
trait IteratorTrait
|
||||
{
|
||||
/**
|
||||
* Index of the current element's key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $IteratorTrait_index = null;
|
||||
|
||||
/**
|
||||
* Array of keys of the data set.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $IteratorTrait_keys = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the current element.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function current()
|
||||
{
|
||||
return $this->valid() ? $this->DataProvider_DATA[$this->key()] : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the key of the current element.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function key()
|
||||
{
|
||||
return static::valid() ? $this->IteratorTrait_keys[$this->IteratorTrait_index] : null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Move forward to next element.
|
||||
*
|
||||
* @return bool false if invalid
|
||||
*/
|
||||
public function next()
|
||||
{
|
||||
$this->IteratorTrait_index++;
|
||||
if (!$this->valid()) {
|
||||
$this->IteratorTrait_index = null;
|
||||
}
|
||||
return $this->valid();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Rewind the Iterator to the first element.
|
||||
*/
|
||||
public function rewind()
|
||||
{
|
||||
$this->IteratorTrait_keys = array_keys($this->DataProvider_DATA);
|
||||
sort($this->IteratorTrait_keys);
|
||||
$this->IteratorTrait_index = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Checks if current position is valid.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function valid(): bool
|
||||
{
|
||||
return ($this->IteratorTrait_index !== null)
|
||||
&& array_key_exists($this->IteratorTrait_index, $this->IteratorTrait_keys)
|
||||
&& array_key_exists($this->IteratorTrait_keys[$this->IteratorTrait_index], $this->DataProvider_DATA);
|
||||
}
|
||||
}
|
||||
@@ -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 LanguageNotInitializedException extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -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 UnsupportedLocaleStringException extends \RuntimeException
|
||||
{
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Dataaccess\DataProvider;
|
||||
|
||||
/**
|
||||
* Country Codes - ISO 3166.
|
||||
* Loads the data and holds the filtered (if desired) list.
|
||||
*
|
||||
* @see https://www.iso.org/iso-3166-country-codes.html
|
||||
* @see DataProvider
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
* @license AGPL-3.0-only
|
||||
*/
|
||||
class Iso3166 extends DataProvider
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataProvider::getOriginalData()
|
||||
*/
|
||||
protected function getOriginalData(): array
|
||||
{
|
||||
return include(__DIR__ . '/data/Iso3166data.php');
|
||||
}
|
||||
}
|
||||
@@ -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\Iso3166\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilter;
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
|
||||
/**
|
||||
* This filter returns all records from the data set (aka dummy filter).
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class All extends DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
|
||||
*/
|
||||
function selectItem(&$key, &$val): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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\Iso3166\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
use Xentral\Components\I18n\Iso3166\Key;
|
||||
|
||||
|
||||
/**
|
||||
* Applies a filter to only select central european countries.
|
||||
*
|
||||
* @see Custom
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class CentralEurope extends Custom implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Countries in Europe.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
const CentralEurope_Countries = ['CHE', 'DEU', 'AUT', 'ITA', 'FRA', 'ESP', 'PRT', 'GBR'];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set predefined values.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(static::CentralEurope_Countries, Key::ALPHA_3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?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\Iso3166\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilter;
|
||||
|
||||
|
||||
/**
|
||||
* This filter can be used to change the main key
|
||||
* of the data set.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class ChangeKey extends DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* New key to use for the data set.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $ChangeKey_key = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize filter and set the new key.
|
||||
*
|
||||
* @param mixed $key
|
||||
*/
|
||||
public function __construct($key)
|
||||
{
|
||||
$this->ChangeKey_key = $key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
|
||||
*/
|
||||
protected function selectItem(&$key, &$val): bool
|
||||
{
|
||||
$key = $val[$this->ChangeKey_key];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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\Iso3166\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilter;
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Apply a custom filter to the data set.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class Custom extends DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Array of wanted values.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $Custom_values = null;
|
||||
|
||||
/**
|
||||
* Key to check for the values in $this->Custom_values.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $Custom_key = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set values for filter.
|
||||
*
|
||||
* @param array $values
|
||||
* @param mixed $key
|
||||
*/
|
||||
public function __construct(array $values, $key)
|
||||
{
|
||||
$this->Custom_values = $values;
|
||||
$this->Custom_key = $key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
|
||||
*/
|
||||
protected function selectItem(&$key, &$val): bool
|
||||
{
|
||||
$needle = $val[$this->Custom_key];
|
||||
return in_array($needle, $this->Custom_values);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Iso3166\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
use Xentral\Components\I18n\Iso3166\Key;
|
||||
|
||||
|
||||
/**
|
||||
* Applies a filter to only select european countries.
|
||||
*
|
||||
* @see Custom
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class Europe extends Custom implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Set predefined values.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(['150'], Key::REGION_CODE);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
<?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\Iso3166;
|
||||
|
||||
|
||||
/**
|
||||
* Keys for the iso3166 list.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Iso3166
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class Key/* extends Ruga_Enum*/
|
||||
{
|
||||
/** Key: Alpha-2 code */
|
||||
const ALPHA_2 = 'A2';
|
||||
|
||||
/** Key: Alpha-3 code */
|
||||
const ALPHA_3 = 'A3';
|
||||
|
||||
/** Key: Numeric code */
|
||||
const NUMERIC = 'NUM';
|
||||
|
||||
/** Key: Top Level Domain */
|
||||
const TLD = 'TLD';
|
||||
|
||||
/** Key: Currency Code */
|
||||
const CURRENCY_CODE = 'CURRENCY_CODE';
|
||||
const TELEPHONE_CODE = 'TEL_CODE';
|
||||
const REGION = 'REGION';
|
||||
const REGION_CODE = 'REGION_CODE';
|
||||
const SUBREGION = 'SUBREGION';
|
||||
const SUBREGION_CODE = 'SUBREGION_CODE';
|
||||
const INTERMEDIATEREGION = 'INTERMEDIATEREGION';
|
||||
const INTERMEDIATEREGION_CODE = 'INTERMEDIATEREGION_CODE';
|
||||
const NAME_eng = 'NAME_eng';
|
||||
const NAME_fra = 'NAME_fra';
|
||||
const NAME_deu = 'NAME_deu';
|
||||
|
||||
|
||||
/** Key: Postal country name */
|
||||
const POST = 'POST';
|
||||
|
||||
|
||||
const DEFAULT = self::ALPHA_3;
|
||||
|
||||
|
||||
protected static $fullnameMap = [
|
||||
self::ALPHA_2 => 'ISO 3166 Alpha-2',
|
||||
self::ALPHA_3 => 'ISO 3166 Alpha-3',
|
||||
self::NUMERIC => 'ISO 3166 Numerisch',
|
||||
self::TLD => 'Top Level Domain',
|
||||
self::CURRENCY_CODE => 'Währung',
|
||||
self::TELEPHONE_CODE => 'Landesvorwahl',
|
||||
self::REGION => 'Region',
|
||||
self::REGION_CODE => 'Region Code',
|
||||
self::SUBREGION => 'Unter-Region',
|
||||
self::SUBREGION_CODE => 'Unter-Region Code',
|
||||
self::INTERMEDIATEREGION => 'Intermediate-Region',
|
||||
self::INTERMEDIATEREGION_CODE => 'Intermediate-Region Code',
|
||||
self::NAME_eng => 'Englische Bezeichnung',
|
||||
self::NAME_fra => 'Französische Bezeichnung',
|
||||
self::NAME_deu => 'Deutsche Bezeichnung',
|
||||
|
||||
self::POST => 'Landesbezeichung Postadresse',
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Iso3166;
|
||||
|
||||
/**
|
||||
* Names for the iso3166 list.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Iso3166
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class Name/* extends Ruga_Enum */
|
||||
{
|
||||
/** Englisch */
|
||||
const ENG = 'NAME_eng';
|
||||
/** Französisch */
|
||||
const FRA = 'NAME_fra';
|
||||
/** Deutsch */
|
||||
const DEU = 'NAME_deu';
|
||||
|
||||
|
||||
protected static $fullnameMap = [
|
||||
self::ENG => 'Englische Bezeichnung',
|
||||
self::FRA => 'Französische Bezeichnung',
|
||||
self::DEU => 'Deutsche Bezeichnung',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?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\Dataaccess\DataProvider;
|
||||
use Xentral\Components\I18n\Dataaccess\Exception\OutOfRangeException;
|
||||
|
||||
/**
|
||||
* Codes for the Representation of Names of Languages - ISO 639.
|
||||
* Loads the data and holds the filtered (if desired) list.
|
||||
*
|
||||
* @see https://www.iso.org/iso-639-language-codes.html
|
||||
* @see DataProvider
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class Iso639 extends DataProvider
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataProvider::getOriginalData()
|
||||
*/
|
||||
protected function getOriginalData(): array
|
||||
{
|
||||
return include(__DIR__ . '/data/Iso639data.php');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the field $desiredName from the record $id.
|
||||
*
|
||||
* @param mixed $id
|
||||
* @param string $desiredName
|
||||
* @param null $default
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function find($id, $desiredName, $default = null): string
|
||||
{
|
||||
$id = strtolower($id);
|
||||
try {
|
||||
return $this->getString($id, $desiredName);
|
||||
} catch (OutOfRangeException $e) {
|
||||
try {
|
||||
return (new \Xentral\Components\I18n\Iso639(
|
||||
(new \Xentral\Components\I18n\Iso639\Filter\All())
|
||||
->then(new \Xentral\Components\I18n\Iso639\Filter\ChangeKey(\Xentral\Components\I18n\Iso639\Key::ALPHA_2))
|
||||
))->getString($id, $desiredName);
|
||||
} catch (OutOfRangeException $e) {
|
||||
try {
|
||||
$id = strtoupper($id);
|
||||
return (new \Xentral\Components\I18n\Iso639(
|
||||
(new \Xentral\Components\I18n\Iso639\Filter\All())
|
||||
->then(new \Xentral\Components\I18n\Iso639\Filter\ChangeKey(\Xentral\Components\I18n\Iso639\Key::ONELETTER))
|
||||
))->getString($id, $desiredName);
|
||||
} catch (OutOfRangeException $e) {
|
||||
if ($default === null) {
|
||||
throw $e;
|
||||
} else {
|
||||
return $this->getString($default, $desiredName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?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\Iso639\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilter;
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
|
||||
|
||||
/**
|
||||
* This filter returns all records from the data set (aka dummy filter).
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class All extends DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
|
||||
*/
|
||||
function selectItem(&$key, &$val): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
<?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\Iso639\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
use Xentral\Components\I18n\Iso639\Key;
|
||||
|
||||
|
||||
/**
|
||||
* Applies a filter to only select central european countries.
|
||||
*
|
||||
* @see Custom
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class CentralEurope extends Custom implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Countries in Europe.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
const CentralEurope_Languages = ['deu', 'fra', 'ita', 'roh', 'spa', 'por', 'eng'];
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set predefined values.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct(static::CentralEurope_Languages, Key::ALPHA_3);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
<?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\Iso639\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilter;
|
||||
|
||||
|
||||
/**
|
||||
* This filter can be used to change the main key
|
||||
* of the data set.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class ChangeKey extends DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* New key to use for the data set.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $ChangeKey_key = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Initialize filter and set the new key.
|
||||
*
|
||||
* @param mixed $key
|
||||
*/
|
||||
public function __construct($key)
|
||||
{
|
||||
$this->ChangeKey_key = $key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
|
||||
*/
|
||||
protected function selectItem(&$key, &$val): bool
|
||||
{
|
||||
$key = $val[$this->ChangeKey_key] ?? null;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
<?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\Iso639\Filter;
|
||||
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilter;
|
||||
use Xentral\Components\I18n\Dataaccess\DataFilterInterface;
|
||||
|
||||
|
||||
/**
|
||||
* Apply a custom filter to the data set.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilter
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
class Custom extends DataFilter implements DataFilterInterface
|
||||
{
|
||||
/**
|
||||
* Array of wanted values.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $Custom_values = null;
|
||||
|
||||
/**
|
||||
* Key to check for the values in $this->Custom_values.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
private $Custom_key = null;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set values for filter.
|
||||
*
|
||||
* @param array $values
|
||||
* @param mixed $key
|
||||
*/
|
||||
public function __construct(array $values, $key)
|
||||
{
|
||||
$this->Custom_values = $values;
|
||||
$this->Custom_key = $key;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @see \Xentral\Components\I18n\Dataaccess\DataFilterInterface::selectItem()
|
||||
*/
|
||||
protected function selectItem(&$key, &$val): bool
|
||||
{
|
||||
$needle = $val[$this->Custom_key];
|
||||
return in_array($needle, $this->Custom_values);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?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\Iso639;
|
||||
|
||||
|
||||
/**
|
||||
* Keys for the iso639 list.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Iso639
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class Key/* extends Ruga_Enum*/
|
||||
{
|
||||
/** Key: Alpha-2 code */
|
||||
const ALPHA_2 = '639-1';
|
||||
const ISO639_1 = '639-1';
|
||||
|
||||
/** Key: Alpha-3 code */
|
||||
const ALPHA_3 = '639-2';
|
||||
const ISO639_2 = '639-2';
|
||||
|
||||
/** Key: Top Level Domain */
|
||||
const ONELETTER = '1L';
|
||||
|
||||
/** Key: Name */
|
||||
const NAME_eng = 'NAME_eng';
|
||||
const NAME_fra = 'NAME_fra';
|
||||
const NAME_deu = 'NAME_deu';
|
||||
|
||||
|
||||
const DEFAULT = self::ALPHA_3;
|
||||
|
||||
|
||||
protected static $fullnameMap = [
|
||||
self::ALPHA_2 => 'ISO 639 Alpha-2',
|
||||
self::ALPHA_3 => 'ISO 639 Alpha-3',
|
||||
self::ONELETTER => 'ISO 639 Alpha-1',
|
||||
self::NAME_eng => 'Englische Bezeichnung',
|
||||
self::NAME_fra => 'Französische Bezeichnung',
|
||||
self::NAME_deu => 'Deutsche Bezeichnung',
|
||||
];
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
<?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\Iso639;
|
||||
|
||||
|
||||
/**
|
||||
* Names for the iso639 list.
|
||||
*
|
||||
* @see \Xentral\Components\I18n\Iso639
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
abstract class Name/* extends Ruga_Enum */
|
||||
{
|
||||
/** Englisch */
|
||||
const ENG = 'NAME_eng';
|
||||
/** Französisch */
|
||||
const FRA = 'NAME_fra';
|
||||
/** Deutsch */
|
||||
const DEU = 'NAME_deu';
|
||||
|
||||
|
||||
protected static $fullnameMap = [
|
||||
self::ENG => 'Englische Bezeichnung',
|
||||
self::FRA => 'Französische Bezeichnung',
|
||||
self::DEU => 'Deutsche Bezeichnung',
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,244 @@
|
||||
<?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 Locale;
|
||||
use Xentral\Components\Http\Request;
|
||||
use Xentral\Components\Http\Session\Session;
|
||||
use Xentral\Components\I18n\Exception\LanguageNotInitializedException;
|
||||
use Xentral\Components\I18n\Exception\UnsupportedLocaleStringException;
|
||||
|
||||
/**
|
||||
* Provides a central service for localization.
|
||||
*
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
final class Localization implements LocalizationInterface
|
||||
{
|
||||
private array $config;
|
||||
|
||||
private ?Request $request;
|
||||
|
||||
private ?Session $session;
|
||||
|
||||
private array $usersettings = [];
|
||||
|
||||
private array $language = [];
|
||||
|
||||
private array $locale = [];
|
||||
|
||||
|
||||
|
||||
public function __construct(?Request $request, ?Session $session, array $usersettings = [], array $config = [])
|
||||
{
|
||||
$this->request = $request;
|
||||
$this->session = $session;
|
||||
$this->usersettings = $usersettings;
|
||||
$this->config = $config;
|
||||
$this->process();
|
||||
}
|
||||
|
||||
|
||||
|
||||
public function process()
|
||||
{
|
||||
// Hardcoded defaults if config is not available
|
||||
$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';
|
||||
|
||||
// Get the locale from the session, if available
|
||||
if ($this->session && ($locale = $this->session->getValue($segmentName, $localeAttrName))) {
|
||||
} 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
|
||||
);
|
||||
} else {
|
||||
$locale = Locale::acceptFromHttp($_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? $localeDefault);
|
||||
}
|
||||
}
|
||||
// Get locale from user
|
||||
// This overrides all previous attempts to find a locale
|
||||
if (array_key_exists('locale', $this->usersettings)) {
|
||||
$locale = $this->usersettings['locale'];
|
||||
}
|
||||
// Get locale from query string
|
||||
// This overrides all previous attempts to find a locale
|
||||
if ($this->request) {
|
||||
$locale = $this->request->getParam($localeAttrName, $locale ?? $localeDefault);
|
||||
} else {
|
||||
$locale = $_GET[$localeAttrName] ?? $locale ?? $localeDefault;
|
||||
}
|
||||
|
||||
|
||||
// Get the language from the session, if available
|
||||
if ($this->session && ($language = $this->session->getValue($segmentName, $langAttrName))) {
|
||||
} else {
|
||||
// Get language from request, fallback to the current locale
|
||||
if ($this->request) {
|
||||
$language = $this->request->attributes->get($langAttrName, Locale::getPrimaryLanguage($locale));
|
||||
} else {
|
||||
$language = Locale::getPrimaryLanguage($locale);
|
||||
}
|
||||
}
|
||||
// Get language from user
|
||||
// This overrides all previous attempts to find a language
|
||||
if (array_key_exists('language', $this->usersettings)) {
|
||||
$language = $this->usersettings['language'];
|
||||
}
|
||||
// Get language from query string
|
||||
// This overrides all previous attempts to find a language
|
||||
if ($this->request) {
|
||||
$language = $this->request->getParam($langAttrName, $language ?? $langDefault);
|
||||
} else {
|
||||
$language = $language ?? $langDefault;
|
||||
}
|
||||
|
||||
// Check language against the data from Iso639 (and normalize to 3-letter-code)
|
||||
$language = (new Iso639())->find($language, Iso639\Key::DEFAULT, $langDefault);
|
||||
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
// Store the locale and language as a request attribute
|
||||
if ($this->request) {
|
||||
$this->request->attributes->set($localeAttrName, $locale);
|
||||
$this->request->attributes->set($langAttrName, $language);
|
||||
}
|
||||
|
||||
// Set the default locale
|
||||
Locale::setDefault($locale);
|
||||
// error_log(self::class . ": {$locale}");
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the language.
|
||||
*
|
||||
* @param string $language
|
||||
*/
|
||||
public function setLanguage(string $language)
|
||||
{
|
||||
$this->language[Iso639\Key::DEFAULT] = (new \Xentral\Components\I18n\Iso639())->find(
|
||||
$language,
|
||||
Iso639\Key::DEFAULT
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the language string as defined by $key.
|
||||
*
|
||||
* @param string|null $key A constant from Iso639\Key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage(string $key = null): string
|
||||
{
|
||||
if (!$key) {
|
||||
$key = Iso639\Key::DEFAULT;
|
||||
}
|
||||
if (!($this->language[$key] ?? null)) {
|
||||
if (!($this->language[Iso639\Key::DEFAULT] ?? null)) {
|
||||
throw new LanguageNotInitializedException("Language is not set for key '" . Iso639\Key::DEFAULT . "'");
|
||||
}
|
||||
$this->language[$key] = (new \Xentral\Components\I18n\Iso639())->find(
|
||||
$this->language[Iso639\Key::DEFAULT],
|
||||
$key
|
||||
);
|
||||
}
|
||||
return $this->language[$key];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the locale.
|
||||
*
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setLocale(string $locale)
|
||||
{
|
||||
$parsedLocale = Locale::parseLocale($locale);
|
||||
$locale = Locale::composeLocale([
|
||||
'language' => $parsedLocale['language'],
|
||||
'region' => $parsedLocale['region'],
|
||||
]);
|
||||
|
||||
if(!$locale) throw new UnsupportedLocaleStringException("The given locale string '{$locale}' is not supported");
|
||||
|
||||
$this->locale[Iso3166\Key::DEFAULT] = $locale;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
{
|
||||
return $this->locale[Iso3166\Key::DEFAULT];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a new localization object using the given adresse array as source for language and region.
|
||||
*
|
||||
* @param array $adresse
|
||||
*
|
||||
* @return $this
|
||||
*/
|
||||
public function withAdresse(array $adresse): self
|
||||
{
|
||||
$localization = clone $this;
|
||||
|
||||
// Find language from address array or keep current language
|
||||
if (!$lang = Bootstrap::findLanguage($adresse['sprache'])) {
|
||||
$lang = Bootstrap::findLanguage($this->getLanguage());
|
||||
}
|
||||
if ($lang) {
|
||||
$localization->setLanguage($lang[Iso639\Key::ALPHA_3]);
|
||||
}
|
||||
|
||||
// Find region from address or keep current region
|
||||
if (!$region = Bootstrap::findRegion($adresse['land'])) {
|
||||
$parsedLocale = Locale::parseLocale($this->getLocale());
|
||||
$region = Bootstrap::findRegion($parsedLocale['region']);
|
||||
}
|
||||
if ($lang && $region) {
|
||||
$localization->setLocale("{$lang[Iso639\Key::ALPHA_2]}_{$region[Iso3166\Key::ALPHA_2]}");
|
||||
}
|
||||
|
||||
return $localization;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Interface LocalizationInterface
|
||||
*
|
||||
* @author Roland Rusch, easy-smart solution GmbH <roland.rusch@easy-smart.ch>
|
||||
*/
|
||||
interface LocalizationInterface
|
||||
{
|
||||
const LOCALE_DEFAULT = 'locale_default';
|
||||
const LOCALE_ATTRIBUTE_NAME = 'locale_attr_name';
|
||||
const LANGUAGE_DEFAULT = 'language_default';
|
||||
const LANGUAGE_ATTRIBUTE_NAME = 'language_attr_name';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the language.
|
||||
*
|
||||
* @param string $language
|
||||
*/
|
||||
public function setLanguage(string $language);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return the language string as defined by $key.
|
||||
*
|
||||
* @param string|null $key A constant from Iso639\Key
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getLanguage(string $key = null): string;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Set the locale.
|
||||
*
|
||||
* @param string $locale
|
||||
*/
|
||||
public function setLocale(string $locale);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,159 @@
|
||||
<?php
|
||||
/*
|
||||
* Data extracted from https://www.iso.org/iso-639-language-codes.html
|
||||
*/
|
||||
return [
|
||||
|
||||
'aar' => [
|
||||
'639-2' => 'aar',
|
||||
'639-1' => 'aa',
|
||||
'NAME_eng' => 'Afar',
|
||||
'NAME_fra' => 'afar',
|
||||
'NAME_deu' => 'Danakil-Sprache',
|
||||
],
|
||||
'abk' => [
|
||||
'639-2' => 'abk',
|
||||
'639-1' => 'ab',
|
||||
'NAME_eng' => 'Abkhazian',
|
||||
'NAME_fra' => 'abkhaze',
|
||||
'NAME_deu' => 'Abchasisch',
|
||||
],
|
||||
'ace' => [
|
||||
'639-2' => 'ace',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Achinese',
|
||||
'NAME_fra' => 'aceh',
|
||||
'NAME_deu' => 'Aceh-Sprache',
|
||||
],
|
||||
'ach' => [
|
||||
'639-2' => 'ach',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Acoli',
|
||||
'NAME_fra' => 'acoli',
|
||||
'NAME_deu' => 'Acholi-Sprache',
|
||||
],
|
||||
'ada' => [
|
||||
'639-2' => 'ada',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Adangme',
|
||||
'NAME_fra' => 'adangme',
|
||||
'NAME_deu' => 'Adangme-Sprache',
|
||||
],
|
||||
'ady' => [
|
||||
'639-2' => 'ady',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Adyghe',
|
||||
'NAME_fra' => 'adyghé',
|
||||
'NAME_deu' => 'Adygisch',
|
||||
],
|
||||
'afa' => [
|
||||
'639-2' => 'afa',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Afro-Asiatic languages',
|
||||
'NAME_fra' => 'afro-asiatiques, langues',
|
||||
'NAME_deu' => 'Hamitosemitische Sprachen (Andere)',
|
||||
],
|
||||
'afh' => [
|
||||
'639-2' => 'afh',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Afrihili',
|
||||
'NAME_fra' => 'afrihili',
|
||||
'NAME_deu' => 'Afrihili',
|
||||
],
|
||||
'afr' => [
|
||||
'639-2' => 'afr',
|
||||
'639-1' => 'af',
|
||||
'NAME_eng' => 'Afrikaans',
|
||||
'NAME_fra' => 'afrikaans',
|
||||
'NAME_deu' => 'Afrikaans',
|
||||
],
|
||||
'ain' => [
|
||||
'639-2' => 'ain',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Ainu',
|
||||
'NAME_fra' => 'aïnou',
|
||||
'NAME_deu' => 'Ainu-Sprache',
|
||||
],
|
||||
'aka' => [
|
||||
'639-2' => 'aka',
|
||||
'639-1' => 'ak',
|
||||
'NAME_eng' => 'Akan',
|
||||
'NAME_fra' => 'akan',
|
||||
'NAME_deu' => 'Akan-Sprache',
|
||||
],
|
||||
'akk' => [
|
||||
'639-2' => 'akk',
|
||||
'639-1' => null,
|
||||
'NAME_eng' => 'Akkadian',
|
||||
'NAME_fra' => 'akkadien',
|
||||
'NAME_deu' => 'Akkadisch',
|
||||
],
|
||||
'sqi' => [
|
||||
'639-2' => 'sqi',
|
||||
'639-1' => 'sq',
|
||||
'NAME_eng' => 'Albanian',
|
||||
'NAME_fra' => 'albanais',
|
||||
'NAME_deu' => 'Albanisch',
|
||||
'639-2-B' => 'alb',
|
||||
],
|
||||
|
||||
'deu' => [
|
||||
'639-2' => 'deu',
|
||||
'639-1' => 'de',
|
||||
'NAME_eng' => 'German',
|
||||
'NAME_fra' => 'allemand',
|
||||
'NAME_deu' => 'Deutsch',
|
||||
'639-2-B' => 'ger',
|
||||
'1L' => 'D',
|
||||
],
|
||||
'eng' => [
|
||||
'639-2' => 'eng',
|
||||
'639-1' => 'en',
|
||||
'NAME_eng' => 'English',
|
||||
'NAME_fra' => 'anglais',
|
||||
'NAME_deu' => 'Englisch',
|
||||
'1L' => 'E',
|
||||
],
|
||||
'fra' => [
|
||||
'639-2' => 'fra',
|
||||
'639-1' => 'fr',
|
||||
'NAME_eng' => 'French',
|
||||
'NAME_fra' => 'français',
|
||||
'NAME_deu' => 'Französisch',
|
||||
'639-2-B' => 'fre',
|
||||
'1L' => 'F',
|
||||
],
|
||||
'ita' => [
|
||||
'639-2' => 'ita',
|
||||
'639-1' => 'it',
|
||||
'NAME_eng' => 'Italian',
|
||||
'NAME_fra' => 'italien',
|
||||
'NAME_deu' => 'Italienisch',
|
||||
'1L' => 'I',
|
||||
],
|
||||
'spa' => [
|
||||
'639-2' => 'spa',
|
||||
'639-1' => 'es',
|
||||
'NAME_eng' => 'Spanish',
|
||||
'NAME_fra' => 'espagnol',
|
||||
'NAME_deu' => 'Spanisch',
|
||||
],
|
||||
'por' => [
|
||||
'639-2' => 'por',
|
||||
'639-1' => 'pt',
|
||||
'NAME_eng' => 'Portuguese',
|
||||
'NAME_fra' => 'portugais',
|
||||
'NAME_deu' => 'Portugiesisch',
|
||||
],
|
||||
'roh' => [
|
||||
'639-2' => 'roh',
|
||||
'639-1' => 'rm',
|
||||
'NAME_eng' => 'Romansh',
|
||||
'NAME_fra' => 'romanche',
|
||||
'NAME_deu' => 'Rätoromanisch',
|
||||
],
|
||||
'dut' => ['639-2' => 'dut', '639-1' => 'nl', 'NAME_eng' => 'Dutch', 'NAME_fra' => 'néerlandais', 'NAME_deu' => 'Niederländisch', 'NAME_deu_alt' => 'Holländisch'],
|
||||
'swe' => ['639-2' => 'swe', '639-1' => 'sv', 'NAME_eng' => 'Swedish', 'NAME_fra' => 'suédois', 'NAME_deu' => 'Schwedisch'],
|
||||
'dan' => ['639-2' => 'dan', '639-1' => 'da', 'NAME_eng' => 'Danish', 'NAME_fra' => 'danois', 'NAME_deu' => 'Dänisch'],
|
||||
'nor' => ['639-2' => 'nor', '639-1' => 'no', 'NAME_eng' => 'Norwegian', 'NAME_fra' => 'norvégien', 'NAME_deu' => 'Norwegisch'],
|
||||
];
|
||||
@@ -12108,6 +12108,9 @@ url:strUrl, success:function(html){strReturn = html;}, async:false
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table></div>
|
||||
<br>
|
||||
<br>
|
||||
<br>
|
||||
');
|
||||
|
||||
if((empty($disableautosavefilter)) && $this->anzusersaves < 2) {
|
||||
|
||||
@@ -64785,17 +64785,6 @@
|
||||
"Extra": "",
|
||||
"Privileges": "select,insert,update,references",
|
||||
"Comment": ""
|
||||
},
|
||||
{
|
||||
"Field": "vorlaeufig",
|
||||
"Type": "int(1)",
|
||||
"Collation": null,
|
||||
"Null": "YES",
|
||||
"Key": "",
|
||||
"Default": "",
|
||||
"Extra": "",
|
||||
"Privileges": "select,insert,update,references",
|
||||
"Comment": ""
|
||||
}
|
||||
],
|
||||
"keys": [
|
||||
|
||||
@@ -26040,7 +26040,7 @@ function ChargenMHDAuslagern($artikel, $menge, $lagerplatztyp, $lpid,$typ,$wert,
|
||||
$this->app->Tpl->Set('DRUCKER', $this->GetSelectDrucker($selected));
|
||||
}
|
||||
$this->app->Tpl->Set('FAX',$this->GetSelectFax());
|
||||
$this->app->Tpl->Set('EMAILEMPFAENGER',$this->GetSelectEmail($this->Firmendaten("email")));
|
||||
$this->app->Tpl->Set('EMAILEMPFAENGER',$this->GetSelectEmail());
|
||||
$projektabkuerzung = $this->app->DB->Select("SELECT abkuerzung FROM projekt WHERE id='$projekt'");
|
||||
$this->app->Tpl->Set('PROJEKT',$projektabkuerzung);
|
||||
//$this->app->Tpl->Set(PROJEKT,$this->GetProjektSelect($projekt));
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
<fieldset>
|
||||
<table width="100%" border="0" class="mkTableFormular">
|
||||
<legend>{|[STATUSICON]<b>Ticket <font color="blue">#[SCHLUESSEL]</font></b>|}</legend>
|
||||
<tr><td>{|Betreff|}:</td><td><input type="text" name="betreff" id="betreff" value="[BETREFF]" size="100%"></td></tr>
|
||||
<tr><td>{|Betreff|}:</td><td><input type="text" name="betreff" id="betreff" value="[BETREFF]" size="20"></td></tr>
|
||||
<tr><td>{|Von|}:</td><td>[KUNDE] [MAILADRESSE]</td></tr>
|
||||
<tr><td>{|Projekt|}:</td><td><input type="text" name="projekt" id="projekt" value="[PROJEKT]" size="20"></td></tr>
|
||||
<tr><td>{|Adresse|}:</td><td><input type="text" name="adresse" id="adresse" value="[ADRESSE]" size="20"><a href="index.php?module=adresse&action=edit&id=[ADRESSE_ID]"><img src="./themes/new/images/forward.svg" border="0" style="top:6px; position:relative"></a></td></tr>
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
<!--
|
||||
<table id="table[MD5]">
|
||||
<tr><td>{|Lieferschein|}:</td><td><input type="checkbox" onchange="lsclick[MD5]();" id="beiback_lieferschein[MD5]" disabled value="1" [BEIPACK_LIEFERSCHEIN] /></td><td><span id="lsnr[MD5]">[LSNR]</span></td>
|
||||
<td><input type="button" value="{|Belege ändern|}" style="cursor:hand;" onclick="editclick[MD5]();" /></td>
|
||||
</tr>
|
||||
<tr><td>{|Lieferschein|}:</td><td><input type="checkbox" onchange="lsclick[MD5]();" id="beiback_lieferschein[MD5]" disabled value="1" [BEIPACK_LIEFERSCHEIN] /></td><td><span id="lsnr[MD5]">[LSNR]</span></td><td><input type="button" value="{|Belege ändern|}" style="cursor:hand;" onclick="editclick[MD5]();" /></td></tr>
|
||||
<tr><td>{|Rechnung|}:</td><td><input type="checkbox" onchange="reclick[MD5]();" id="beiback_rechnung[MD5]" disabled value="1" [BEIPACK_RECHNUNG] /></td><td><span id="renr[MD5]">[RENR]</span></td><td></td></tr>
|
||||
</table>
|
||||
-->
|
||||
|
||||
<table width="100%">
|
||||
<tr><td width="100%">[ARTIKEL]</td></tr>
|
||||
@@ -114,4 +110,4 @@ $(document).ready(function() {
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
</script>
|
||||
@@ -11,7 +11,9 @@
|
||||
<input type="hidden" id="paketannahme_id" value="[ID]" />
|
||||
[BEFORETAB1]
|
||||
<div id="tabs-1">
|
||||
|
||||
[TAB1START]
|
||||
|
||||
[MESSAGE1]
|
||||
<form action="" method="post">
|
||||
<div class="row">
|
||||
@@ -24,51 +26,25 @@
|
||||
<tr><td>{|Lieferschein-Nr.|}:</td><td><input type=text size="40" name="lsnr" value=[LSNR]></td></tr>
|
||||
<tr><td>{|Rechnung-Nr.|}:</td><td><input type=text size="40" name="renr" value=[RENR]></td></tr>
|
||||
<tr><td>{|Bemerkung|}:</td><td><textarea rows="5" cols="40" name="bemerkung">[BEMERKUNG]</textarea></td></tr>
|
||||
[ISLIEFERANTSTART]
|
||||
<tr><td>{|Ziellager|}:</td><td><input type=text size="40" name="ziellager" id="ziellager" value=[LAGER]></td></tr>
|
||||
[ISLIEFERANTENDE]
|
||||
<tr><td><input type="submit" name="speichern" class="btnGreenNew" value="Speichern"></td>
|
||||
</table>
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-xs-12 col-md-2 col-md-height">
|
||||
<div class="inside inside-full-height">
|
||||
<fieldset>
|
||||
[BUTTONS]
|
||||
[BEFOREFRM]
|
||||
[AFTERFRM]
|
||||
[DISTRIINHALTBUTTONS]
|
||||
[BEFOREFRM]
|
||||
[AFTERFRM]
|
||||
<table width="100%" border="0" class="mkTableFormular">
|
||||
<legend>{|Aktionen|}</legend>
|
||||
[BEFOREMANUELLERFASSEN]
|
||||
<tr><td>
|
||||
<button name="submit" class="ui-button-icon" style="width:100%;" value="manuellerfassen">{|Artikel manuell erfassen|}</button>
|
||||
</td></tr>
|
||||
[AFTERMANUELLERFASSEN]
|
||||
[ISLIEFERANTSTART]
|
||||
<!--
|
||||
<tr><td>
|
||||
<button name="submit" class="ui-button-icon" style="width:100%;" value="fuellen">{|Aus Bestellungen füllen|}</button>
|
||||
</td></tr>
|
||||
<tr><td>
|
||||
<button name="submit" class="ui-button-icon" style="width:100%;" value="leeren">{|Leeren|}</button>
|
||||
</td></tr>
|
||||
-->
|
||||
[ISLIEFERANTENDE]
|
||||
<tr><td>
|
||||
<button name="submit" class="ui-button-icon" style="width:100%;" value="speichern">{|Speichern|}</button>
|
||||
</td></tr>
|
||||
[ISLIEFERANTSTART]
|
||||
<tr><td>
|
||||
<button name="submit" class="ui-button-icon" style="width:100%;" value="buchen">{|Buchen|}</button>
|
||||
</td></tr>
|
||||
[ISLIEFERANTENDE]
|
||||
<tr><td>
|
||||
<button name="submit" class="ui-button-icon" style="width:100%;" value="abschliessen">{|Abschließen|}</button>
|
||||
</td></tr>
|
||||
</table>
|
||||
<fieldset>
|
||||
<legend>{|Aktionen|}</legend>
|
||||
[BUTTONS]
|
||||
[BEFOREFRM]
|
||||
[AFTERFRM]
|
||||
[DISTRIINHALTBUTTONS]
|
||||
<input type="submit" name="abschliessen" id="btnabschliessen" class="btnGreenNew" value="Paketinhalt ist erfasst">
|
||||
[BEFOREMANUELLERFASSEN]
|
||||
<input type="submit" name="manuellerfassen" class="btnBlueNew" value="Artikel manuell erfassen">
|
||||
[AFTERMANUELLERFASSEN]
|
||||
[BEFOREFRM]
|
||||
[AFTERFRM]
|
||||
</fieldset>
|
||||
</div>
|
||||
</div>
|
||||
@@ -78,7 +54,7 @@
|
||||
<div class="row-height">
|
||||
<div class="col-xs-12 col-md-10 col-md-height">
|
||||
<div class="inside-white inside-full-height">
|
||||
[TAB1]
|
||||
[TAB1]
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -97,7 +97,11 @@
|
||||
<td>{|Sprache|}:</td>
|
||||
<td><select name="sprachebevorzugen" id="sprachebevorzugen">[SPRACHEBEVORZUGEN]</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>{|Sprache und Region|}:</td>
|
||||
<td><input type="text" name="locale" id="locale" value="[LOCALE]" size="40" disabled="disabled"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>{|Eigene Kalenderfarbe|}:</td>
|
||||
<td><input type="text" name="defaultcolor" id="defaultcolor" value="[DEFAULTCOLOR]" size="80"></td>
|
||||
<td></td>
|
||||
|
||||
@@ -401,8 +401,7 @@ class Managementboard
|
||||
/** @var Rechnungslauf $obj */
|
||||
$obj = $this->app->erp->LoadModul('rechnungslauf');
|
||||
if($obj){
|
||||
// $w[24] = $obj->RechnungslaufRechnungslauf(true); // This does not exist, presumably old xentral function
|
||||
$w[24] = 0;
|
||||
$w[24] = $obj->RechnungslaufRechnungslauf(true);
|
||||
}
|
||||
else {
|
||||
$w[24] = 0;
|
||||
|
||||
@@ -68,7 +68,7 @@ class Ticket {
|
||||
$dropnbox = "'<img src=./themes/new/images/details_open.png class=details>' AS `open`,
|
||||
CONCAT('<input type=\"checkbox\" name=\"auswahl[]\" value=\"',t.id,'\" />') AS `auswahl`";
|
||||
|
||||
$priobetreff = "if(t.prio!=1,REGEXP_REPLACE(t.betreff, '<[^>]*>+', ''),CONCAT('<b><font color=red>',REGEXP_REPLACE(t.betreff, '<[^>]*>+', ''),'</font></b>'))"; //+ #20230916 XSS
|
||||
$priobetreff = "if(t.prio!=1,t.betreff,CONCAT('<b><font color=red>',t.betreff,'</font></b>'))";
|
||||
|
||||
$anzahlnachrichten = "(SELECT COUNT(n.id) FROM ticket_nachricht n WHERE n.ticket = t.schluessel)";
|
||||
|
||||
@@ -310,8 +310,6 @@ class Ticket {
|
||||
// Add Messages now
|
||||
foreach ($messages as $message) {
|
||||
|
||||
$message['betreff'] = strip_tags($message['betreff']); //+ #20230916 XSS
|
||||
|
||||
// Clear this first
|
||||
$this->app->Tpl->Set('NACHRICHT_ANHANG',"");
|
||||
|
||||
@@ -624,8 +622,6 @@ class Ticket {
|
||||
|
||||
$ticket_from_db = $this->app->DB->SelectArr($sql)[0];
|
||||
|
||||
$ticket_from_db['betreff'] = htmlentities(strip_tags($ticket_from_db['betreff'])); //+ #20230916 XSS
|
||||
|
||||
foreach ($ticket_from_db as $key => $value) {
|
||||
$this->app->Tpl->Set(strtoupper($key), $value);
|
||||
}
|
||||
@@ -737,10 +733,10 @@ class Ticket {
|
||||
|
||||
if (!empty($recv_messages)) {
|
||||
if (!str_starts_with(strtoupper($recv_messages[0]['betreff']),"RE:")) {
|
||||
$betreff = "RE: ".strip_tags($recv_messages[0]['betreff']); //+ #20230916 XSS
|
||||
$betreff = "RE: ".$recv_messages[0]['betreff'];
|
||||
}
|
||||
else {
|
||||
$betreff = strip_tags($recv_messages[0]['betreff']); //+ #20230916 XSS
|
||||
$betreff = $recv_messages[0]['betreff'];
|
||||
}
|
||||
|
||||
$sql = "SELECT GROUP_CONCAT(DISTINCT `value` ORDER BY `value` SEPARATOR ', ') FROM ticket_header th WHERE th.ticket_nachricht = ".$recv_messages[0]['id']." AND `value` <> '".$senderAddress."' AND type='to'";
|
||||
|
||||
+2404
-2376
File diff suppressed because it is too large
Load Diff
@@ -1711,6 +1711,13 @@ $this->app->Tpl->Add('TODOFORUSER',"<tr><td width=\"90%\">".$tmp[$i]['aufgabe'].
|
||||
$this->app->Tpl->Set('STARTSEITE', $settings['startseite']);
|
||||
$this->app->Tpl->Set('DEFAULTCOLOR', $settings['defaultcolor']);
|
||||
$this->app->Tpl->Set('SPRACHEBEVORZUGEN', $this->languageSelectOptions($settings['sprachebevorzugen']));
|
||||
|
||||
/** @var \Xentral\Components\I18n\Localization $localization */
|
||||
if($localization=$this->app->Container->get('Localization')) {
|
||||
$this->app->Tpl->Set('LOCALE', $localization->getLocale());
|
||||
} else {
|
||||
$this->app->Tpl->Set('LOCALE', 'Fehler!');
|
||||
}
|
||||
|
||||
if($settings['chat_popup']){
|
||||
$this->app->Tpl->Set('CHAT_POPUP', ' checked="checked" ');
|
||||
|
||||
@@ -1,3 +1,37 @@
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-Regular.woff2?v=3.13') format("woff2"),
|
||||
url('../themes/new/fonts/Inter-Regular.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-Italic.woff2?v=3.13') format("woff2"),
|
||||
url('../themes/new/fonts/Inter-Italic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-Bold.woff2?v=3.13') format("woff2"),
|
||||
url('../themes/new/fonts/Inter-Bold.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-BoldItalic.woff2?v=3.13') format("woff2"),
|
||||
url('../themes/new/fonts/Inter-BoldItalic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 16px;
|
||||
font-family: 'Inter', Arial, Helvetica, sans-serif;
|
||||
|
||||
@@ -1,3 +1,38 @@
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-Regular.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Regular.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-Italic.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Italic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Bold.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Bold.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-BoldItalic.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-BoldItalic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,39 @@
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Regular.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Regular.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Italic.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Italic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Bold.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Bold.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../themes/new/fonts/Inter-BoldItalic.woff2?v=3.13') format("woff2"),
|
||||
url('../themes/new/fonts/Inter-BoldItalic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
|
||||
html {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,71 @@
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Regular.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Regular.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Italic.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Italic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("../fonts/Inter-Medium.woff2?v=3.13") format("woff2"),
|
||||
url("../fonts/Inter-Medium.woff?v=3.13") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url("../fonts/Inter-MediumItalic.woff2?v=3.13") format("woff2"),
|
||||
url("../fonts/Inter-MediumItalic.woff?v=3.13") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url("../fonts/Inter-SemiBold.woff2?v=3.13") format("woff2"),
|
||||
url("../fonts/Inter-SemiBold.woff?v=3.13") format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url("../fonts/Inter-SemiBoldItalic.woff2?v=3.13") format("woff2"),
|
||||
url("../fonts/Inter-SemiBoldItalic.woff?v=3.13") format("woff");
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-Bold.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-Bold.woff?v=3.13') format("woff");
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../fonts/Inter-BoldItalic.woff2?v=3.13') format("woff2"),
|
||||
url('../fonts/Inter-BoldItalic.woff?v=3.13') format("woff");
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 12px;
|
||||
font-family: 'Inter', Arial, Helvetica, sans-serif;
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -149,11 +149,12 @@ $(document).ready(function(){
|
||||
<tr valign="top"><td>{|Liefersperre Grund|}:</td><td>[LIEFERSPERREGRUND][MSGLIEFERSPERREGRUND]</td></tr>
|
||||
<tr><td colspan="2"><br></td></tr>
|
||||
<tr><td>{|Sprache für Belege|}:</td><td>[SPRACHE][MSGSPRACHE]</td></tr>
|
||||
<tr><td>{|Sprache und Region|}:</td><td>[LOCALE][MSGLOCALE]</td></tr>
|
||||
|
||||
<tr><td>{|Kundenfreigabe|}:</td><td>[KUNDENFREIGABE][MSGKUNDENFREIGABE] </td></tr>
|
||||
<tr><td colspan="2"><br></td></tr>
|
||||
<tr><td>{|Folgebestätigungsperre|}:</td><td>[FOLGEBESTAETIGUNGSPERRE][MSGFOLGEBESTAETIGUNGSPERRE]</td></tr>
|
||||
<tr><td>{|Trackingmailsperre|}:</td><td>[TRACKINGSPERRE][MSGTRACKINGSPERRE]</td></tr>
|
||||
<tr><td>{|Folgebestätigungsperre|}:</td><td>[FOLGEBESTAETIGUNGSPERRE][MSGFOLGEBESTAETIGUNGSPERRE]</td></tr>
|
||||
<tr><td>{|Trackingmailsperre|}:</td><td>[TRACKINGSPERRE][MSGTRACKINGSPERRE]</td></tr>
|
||||
<tr><td>{|Marketingsperre|}:</td><td>[MARKETINGSPERRE][MSGMARKETINGSPERRE]</td></tr>
|
||||
<tr><td>{|Lead|}:</td><td>[LEAD][MSGLEAD]</td></tr>
|
||||
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
<?php
|
||||
|
||||
use Xentral\Components\Database\Database;
|
||||
|
||||
include ("_gen/widget.gen.adresse.php");
|
||||
|
||||
class WidgetAdresse extends WidgetGenAdresse
|
||||
@@ -284,7 +287,20 @@ class WidgetAdresse extends WidgetGenAdresse
|
||||
$field = new HTMLSelect("sprache",0,"sprache",false,false,"1");
|
||||
$field->AddOptionsSimpleArray($sprachenOptions);
|
||||
$this->form->NewField($field);
|
||||
|
||||
|
||||
/** @var \Xentral\Components\I18n\Localization $localization */
|
||||
$localization=$this->app->Container->get('Localization');
|
||||
/** @var Database $db */
|
||||
$db = $this->app->Container->get('Database');
|
||||
$adresse = $db->fetchRow(
|
||||
$db->select()->cols(['*'])->from('adresse')->where('id=:id'),
|
||||
['id' => $id]
|
||||
);
|
||||
$localization=$localization->withAdresse($adresse);
|
||||
$field = new HTMLInput("locale","text",$localization->getLocale(), size: '10', disabled: 'disabled');
|
||||
$this->form->NewField($field);
|
||||
|
||||
|
||||
$field = new HTMLInput("vorname","hidden","");
|
||||
$this->form->NewField($field);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user