Skip to content

Commit

Permalink
Merge branch 'master' of github.com:/Intermesh/groupoffice
Browse files Browse the repository at this point in the history
  • Loading branch information
derjoachim committed Sep 16, 2024
2 parents 7ec6361 + 18cae88 commit 298de0a
Show file tree
Hide file tree
Showing 26 changed files with 284 additions and 35 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
- Calendar: fix HTML code in Qtip
- Core: Fixed PHP 8.3 compatibility issue: PHP Fatal error: During inheritance of IteratorAggregate: Uncaught ErrorException: Return type of GO\\Base\\Db\\Statement::getIterator() should either be compatible with IteratorAggregate::getIterator(): Traversable, or the #[\\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /var/customers/webs/office/office.domain.tld/go/base/db/Statement.php:578
- Caldav: Fixed users being able to write in read only calendars
- E-mail: Date was lost if message was an smime signed attachment with headers without the date
- Core: Provide date, time and number formatting for csv imports
- Email: fix error when moving or copying to a folder with a % in its name
- Business: add row actions to business grid, fix deleting finance books when deleting business record.
- Business: add row actions to activities grid.
- Finance: Add counter when multiple books of the same type are created upon installation
- Core: Updated German language
- Serverclient: urlencode token

09-09-2024: 6.8.71
- Files: Fix PHPMailer compatibility issue
Expand Down
37 changes: 35 additions & 2 deletions www/go/core/data/convert/Spreadsheet.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace go\core\data\convert;

use Exception;
use go\core\db\Column;
use go\core\event\EventEmitterTrait;
use go\core\fs\Blob;
use go\core\fs\File;
Expand All @@ -16,6 +17,7 @@
use go\core\orm\Query;
use go\core\orm\Relation;
use go\core\util\DateTime as GoDateTime;
use go\core\util\StringUtil;
use PhpOffice\PhpSpreadsheet\Cell\Cell;
use PhpOffice\PhpSpreadsheet\Cell\DataType;
use PhpOffice\PhpSpreadsheet\Spreadsheet as PhpSpreadsheet;
Expand Down Expand Up @@ -579,7 +581,7 @@ private function addSubHeaders($headers, $header, $prop, $many = false, $forMapp
if(!($prop instanceof Relation)) {
if(!$prop->primary) {
//client will define labels if not given. Only custom fields provide label
$headers[$header] = ['name' => $header, 'label' => null, 'many' => $many];
$headers[$header] = ['name' => $header, 'label' => null, 'many' => $many, 'dbType' => $prop->dbType];
}
return $headers;
}
Expand Down Expand Up @@ -711,6 +713,9 @@ private function saveMapping(array $headers) {
}
$mapping->setMap($this->clientParams['mapping']);
$mapping->updateBy =$this->updateBy;
$mapping->thousandsSeparator = $this->clientParams['thousandsSeparator'] ?? null;
$mapping->decimalSeparator = $this->clientParams['decimalSeparator'] ?? null;
$mapping->dateFormat = $this->clientParams['dateFormat'] ?? null;
$mapping->name = $this->saveName;
$mapping->save();

Expand Down Expand Up @@ -832,7 +837,7 @@ protected function importCustomColumns(Entity $entity, $values){
}
return $values;
}

protected function setValues(Entity $entity, array $values) {
$cf = $values['customFields'] ?? null;
unset($values['customFields']);
Expand Down Expand Up @@ -923,6 +928,34 @@ private function convertRecordToProperties($record, $clientMapping, $serverMappi
if(!empty($c['many'])) {
$v[$propName] = explode(static::$multipleDelimiter, $v[$propName]);
}


if($this->extension == 'csv') {
switch ($c['dbType']) {
case 'datetime':
if (isset($this->clientParams['dateFormat']) && isset($this->clientParams['timeFormat'])) {
$dt = \go\core\util\DateTime::createFromFormat($this->clientParams['dateFormat'] . ' ' . $this->clientParams['timeFormat'], $v[$propName]);
if ($dt) {
$v[$propName] = $dt;
}
}

case 'date':

if (isset($this->clientParams['dateFormat'])) {
$dt = \go\core\util\DateTime::createFromFormat($this->clientParams['dateFormat'], $v[$propName]);
if ($dt) {
$v[$propName] = $dt;
}
}

break;

case 'decimal':
$v[$propName] = StringUtil::unlocalizeNumber($v[$propName], $this->clientParams['decimalSeparator'] ?? null, $this->clientParams['thousandsSeparator'] ?? null);
break;
}
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions www/go/core/install/install.sql
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,10 @@ create table core_import_mapping
`name` VARCHAR(120) NOT NULL DEFAULT '(unnamed)',
mapping text null,
updateBy varchar(100) default null null,
dateFormat varchar(20) null,
timeFormat varchar(20) null,
decimalSeparator char null,
thousandsSeparator char null,
PRIMARY KEY (`id`),
constraint core_import_mapping_core_entity_null_fk
foreign key (entityTypeId) references core_entity (id)
Expand Down
14 changes: 14 additions & 0 deletions www/go/core/install/updates.php
Original file line number Diff line number Diff line change
Expand Up @@ -1604,3 +1604,17 @@
add constraint core_acl_ibfk_1
foreign key (entityTypeId) references core_entity (id) on delete set null;";


$updates['202409160946'][] = "alter table core_import_mapping
add dateFormat varchar(20) null;";

$updates['202409160946'][] = "alter table core_import_mapping
add timeFormat varchar(20) null;";

$updates['202409160946'][] = "alter table core_import_mapping
add decimalSeparator char null;";

$updates['202409160946'][] = "alter table core_import_mapping
add thousandsSeparator char null;";


4 changes: 4 additions & 0 deletions www/go/core/jmap/EntityController.php
Original file line number Diff line number Diff line change
Expand Up @@ -1106,6 +1106,10 @@ protected function defaultImportCSVMapping(array $params): ArrayObject
$response['id'] = $mapping->id;
$response['columnMapping'] = $mapping->getColumnMapping();
$response['updateBy'] = $mapping->updateBy;
$response['decimalSeparator'] = $mapping->decimalSeparator;
$response['thousandsSeparator'] = $mapping->thousandsSeparator;
$response['dateFormat'] = $mapping->dateFormat;
$response['timeFormat'] = $mapping->timeFormat;
}

if(!$response) {
Expand Down
35 changes: 33 additions & 2 deletions www/go/core/language/de.php
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@
'KM' => 'Komoren',
'CG' => 'Kongo',
'CK' => 'Cookinseln',
'CI' => 'Côte d\'Ivoire',
'CI' => '\'"Côte d\'\'Ivoire"\'',
'HR' => 'Kroatien',
'CU' => 'Kuba',
'CY' => 'Zypern',
Expand Down Expand Up @@ -1529,7 +1529,7 @@
'At' => 'Um',
'Are you sure you want to dismiss all notifications?' => 'Sind Sie sicher, dass Sie alle Benachrichtigungen verwerfen möchten?',
'Your session is no longer valid. Press OK to authenticate.' => 'Ihre Sitzung ist abgelaufen. Bitte klicken Sie auf OK, um sich neu anzumelden.',
'Permission overview' => 'Berechtigungsübersicht',
'Permission overview' => '„Übersicht über Berechtigung“',
'Main menu' => 'Hauptmenu',
'Browser is offline' => 'Browser ist offline',
'Waiting for connection to return' => 'Warten auf Rückkehr der Verbindung',
Expand Down Expand Up @@ -1625,4 +1625,35 @@
'Your current password' => 'Ihr aktuelles Passwort',
'Enter your administrator password' => 'Geben Sie Ihr Administrator Passwort ein',
'Force password change' => 'Passwortänderung erzwingen',
'\'"You don\'\'t have permission to perform this action"\'' => 'Sie haben keine Befugnis, diese Aktion auszuführen',
'\'"You didn\'\'t select an item."\'' => 'Sie haben keinen Eintrag ausgewählt.',
'\'"The passwords didn\'\'t match"\'' => 'Die Kennwörter stimmen nicht überein',
'\'"You didn\'\'t select anything"\'' => 'Nichts ausgewählt!',
'\'"You can create a function using other number fields. Use the \'\'databaseName\'\' property as tag. For example {foo} + {bar}. You can use the following operators: / , * , + and -"\'' => '\'"Sie können eine Funktion über andere Zahlenfelder anlegen. Verwenden Sie die Eigenschaft\'\'databaseName\'\' als Tag. Zum Beispiel {foo} + {bar}. Sie können die folgenden Operatoren verwenden: /, *, + und - -"\'',
'\'"This name is used in the database and can only contain alphanumeric characters and underscores. It\'\'s only visible to exports and the API."\'' => 'Dieser Name wird in der Datenbank verwendet und darf nur alphanumerische Zeichen und Unterstriche enthalten. Er ist nur für Exporte und die API sichtbar.',
'Edit custom fields' => '„Benutzerdefinierte Felder bearbeiten“',
'\'"All data will be lost! Are you sure you want to delete module \'\'{item}\'\'?"\'' => '\'"Alle Daten werden verloren gehen! Sind Sie sicher, dass Sie das Modul \'\'{item}\'\' löschen wollen?"\'',
'\'"Use $config' =>
array (
'\'\'debug\'\'' => '\' only with development and problem solving. It slows "" + t(\'\'product_name"\'',
),
'\'"Are you sure you want to add the default groups to all items? WARNING: This can\'\'t be undone."\'' => 'Sind Sie sicher, dass Sie die Standardgruppen zu allen Elementen hinzufügen möchten? WARNUNG: Dies kann nicht rückgängig gemacht werden.',
'\'"Are you sure you want to reset all permissions? WARNING: This can\'\'t be undone."\'' => 'Sind Sie sicher, dass Sie alle Berechtigungen zurücksetzen möchten? WARNUNG: Dies kann nicht rückgängig gemacht werden.',
'\'"Sorry, maintenance mode is enabled and you can\'\'t login right now. Please come back later or contact your system administrator"\'' => 'Entschuldigung, der Wartungsmodus ist aktiviert und Sie können sich momentan nicht einloggen. Bitte kommen Sie später wieder oder kontaktieren Sie Ihren Systemadministrator',
'\'"Sorry, maintenance mode is enabled and you can\'\'t login right now. Please come back later or contact your system administrator."\'' => 'Entschuldigung, der Wartungsmodus ist aktiviert und Sie können sich momentan nicht einloggen. Bitte kommen Sie später wieder oder kontaktieren Sie Ihren Systemadministrator',
'\'"Setting \'\'0\'\' will disable uploads for this user. Leave this field empty to allow unlimited space."\'' => '\'"Die Einstellung \'\'0\'\' deaktiviert Uploads für diesen Benutzer. Lassen Sie dieses Feld leer, um unbegrenzt Platz zu schaffen."\'',
'\'"Please match the CSV columns with the correct Group-Office columns and press \'\'Import\'\' to continue."\'' => 'Bitte stimmen Sie die CSV-Spalten mit den richtigen -Spalten ab und klicken Sie auf "Importieren", um fortzufahren.',
'\'"Don\'\'t update"\'' => 'Nicht updaten',
'\'"Logout users when inactive for more than this number of seconds. This will also disable the \'\'Remember my login\'\' checkbox in the login dialog. 0 disables this setting."\'' => 'Benutzer abmelden, wenn sie länger als diese Anzahl von Sekunden inaktiv sind. Dadurch wird auch das Kontrollkästchen "Anmeldung merken" im Anmeldedialog deaktiviert. 0 deaktiviert diese Einstellung.',
'\'"Some fields on this page can\'\'t be edited because they have been locked in the server configuration file."\'' => 'Einige Felder auf dieser Seite können nicht bearbeitet werden, weil sie in der Server-Konfigurationsdatei gesperrt wurden.',
'\'"Please choose if you\'\'d like to allow desktop notifications by Group-Office after pressing \'\'Ok\'\'."\'' => '\'"Bitte wählen Sie die Einstellungen für die Benachrichtigungsanzeige für {product_name} nach Klick auf \'\'Ok\'\'."\'',
'Permissions overview' => '„Übersicht über Berechtigungen“',
'\'"You can\'\' t archive yourself"\'' => 'Sie können sich nicht selbst archivieren',
'\'"Sorry, you don\'\'t have permissions to update this item"\'' => 'Sie sind nicht berechtigt, dieses Objekt zu aktualisieren',
'Please enter a description' => '„Bitte eine Beschreibung eingeben“',
'\'"Reading from your clipboard isn\'\'t supported"\'' => 'Lesen aus der Zwischenablage wird nicht unterstützt',
'\'"Reading from your clipboard isn\'\'t allowed"\'' => 'Lesen aus der Zwischenablage ist nicht erlaubt',
'\'"Do you wish to overwrite the file \'\'{file}\'\'?"\'' => '\'"Möchten Sie die Datei \'\'{file}\'\' überschreiben?"\'',
'\'"Can\'\'t delete the default item."\'' => 'Das Standardobjekt kann nicht gelöscht werden.',
'\'"Please save first by clicking \'\'Apply\'\'"\'' => '\'"Bitte erst mit einem Klick auf \'\'Anwenden\'\' speichern"\'',
);
5 changes: 5 additions & 0 deletions www/go/core/model/ImportMapping.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class ImportMapping extends Entity {
protected $mapping;
public $updateBy;

public ?string $thousandsSeparator = null;
public ?string $decimalSeparator = null;
public ?string $dateFormat = null;
public ?string $timeFormat = null;

protected static function defineMapping(): Mapping
{
return parent::defineMapping()
Expand Down
12 changes: 8 additions & 4 deletions www/go/core/util/DateTime.php
Original file line number Diff line number Diff line change
Expand Up @@ -73,12 +73,16 @@ public function toUserFormat(bool $withTime = false, User $user = null): string
* @param string $format
* @param string $datetime
* @param DateTimeZone|null $timezone
* @return static
* @throws Exception
* @return DateTime|false
* @throws \DateMalformedStringException
*/
public static function createFromFormat(string $format, string $datetime, DateTimeZone $timezone = null): DateTime
public static function createFromFormat(string $format, string $datetime, DateTimeZone $timezone = null): DateTime | false
{
return new static("@" . parent::createFromFormat($format, $datetime, $timezone)->format("U"));
$dt = parent::createFromFormat($format, $datetime, $timezone);
if($dt === false) {
return false;
}
return new static("@" . $dt->format("U"));
}

/**
Expand Down
20 changes: 14 additions & 6 deletions www/go/core/util/StringUtil.php
Original file line number Diff line number Diff line change
Expand Up @@ -1236,17 +1236,25 @@ public static function localizeNumber(?int $number = null, int $decimals = 2): s
* @access public
* @return float|null|bool
*/
public static function unlocalizeNumber(string $number = "")
public static function unlocalizeNumber(string $number = "", string $decimalSeparator = null, string $thousandsSeparator = null)
{
if ($number == "") {
return null;
}
$user = go()->getAuthState()->getUser(['thousandsSeparator', 'decimalSeparator']);

$ts = $user ? $user->thousandsSeparator : go()->getConfig()['default_thousands_separator'];
$ds = $user ? $user->decimalSeparator : go()->getConfig()['default_decimal_separator'];
$number = str_replace($ts, '', $number);
$number = str_replace($ds, '.', $number);
if(!isset($decimalSeparator) || !isset($thousandsSeparator)) {
$user = go()->getAuthState()->getUser(['thousandsSeparator', 'decimalSeparator']);
}

if(!isset($thousandsSeparator)) {
$thousandsSeparator = $user ? $user->thousandsSeparator : go()->getConfig()['default_thousands_separator'];
}
if(!isset($decimalSeparator)) {
$decimalSeparator = $user ? $user->decimalSeparator : go()->getConfig()['default_decimal_separator'];
}

$number = str_replace($thousandsSeparator, '', $number);
$number = str_replace($decimalSeparator, '.', $number);

if (!empty($number) && !is_numeric($number)) {
return false;
Expand Down
Loading

0 comments on commit 298de0a

Please sign in to comment.