Merge branch 'release/2.7.0' into develop

# Conflicts:
#	.make/license/gen-community-license.sh
#	setup/licenses/community-licenses.xml
This commit is contained in:
Pierre Goiffon
2020-03-27 15:20:08 +01:00
50 changed files with 577 additions and 273 deletions

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design version="1.7">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<constants>
</constants>
<classes>

View File

@@ -38,6 +38,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:UserLocal/Attribute:expiration/Value:force_expire+' => '',
'Class:UserLocal/Attribute:password_renewed_date' => 'Passworterneuerung',
'Class:UserLocal/Attribute:password_renewed_date+' => 'Letztes Änderungsdatum',
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Das Passwort muss mindestens 8 Zeichen lang sein und Großbuchstaben, Kleinbuchstaben, Zahlen und Sonderzeichen enthalten.',
'UserLocal:password:expiration' => 'Die folgenden Felder benötigen eine iTop Erweiterung'
));

View File

@@ -249,6 +249,14 @@ class UserLocal extends UserInternal
$config = MetaModel::GetConfig();
}
//if the $proposedValue is an ormPassword, then it cannot be checked
//this if is even more permissive as we can only check against strings
if (!is_string($proposedValue) && !empty($proposedValue))
{
$this->m_oPasswordValidity = new UserLocalPasswordValidity(true);
return;
}
if (null == $aValidatorCollection)
{
$aValidatorCollection = MetaModel::EnumPlugins('iModuleExtension', 'UserLocalPasswordValidator');

View File

@@ -104,10 +104,6 @@ class DatabaseAnalyzer
*/
public function CheckIntegrity($aClassSelection)
{
// Getting and setting time limit are not symetric:
// www.php.net/manual/fr/function.set-time-limit.php#72305
$iPreviousTimeLimit = ini_get('max_execution_time');
$aErrorsAndFixes = array();
if (empty($aClassSelection))
@@ -125,13 +121,10 @@ class DatabaseAnalyzer
$aClassSelection = array_unique($aClassSelection);
}
foreach($aClassSelection as $sClass)
foreach ($aClassSelection as $sClass)
{
// Check uniqueness rules
if (method_exists('MetaModel', 'GetUniquenessRules'))
{
$this->CheckUniquenessRules($sClass, $aErrorsAndFixes);
}
$this->CheckUniquenessRules($sClass, $aErrorsAndFixes);
if (!MetaModel::HasTable($sClass))
{
@@ -144,13 +137,16 @@ class DatabaseAnalyzer
if (!MetaModel::IsStandaloneClass($sClass))
{
$sRootTable = MetaModel::DBGetTable($sRootClass);
$sRootKey = MetaModel::DBGetKey($sRootClass);
if (!MetaModel::IsRootClass($sClass))
{
$sRootTable = MetaModel::DBGetTable($sRootClass);
$sRootKey = MetaModel::DBGetKey($sRootClass);
$this->CheckRecordsInRootTable($sTable, $sKeyField, $sRootTable, $sRootKey, $sClass, $aErrorsAndFixes);
$this->CheckRecordsInChildTable($sRootClass, $sClass, $sRootTable, $sRootKey, $sTable, $sKeyField, $aErrorsAndFixes);
if (!MetaModel::IsLeafClass($sClass))
{
$this->CheckIntermediateFinalClass($sRootClass, $sClass, $sRootTable, $sRootKey, $sTable, $sKeyField, $aErrorsAndFixes);
}
}
}
@@ -174,10 +170,6 @@ class DatabaseAnalyzer
}
$this->CheckUsers($aErrorsAndFixes);
if (!is_null($this->iTimeLimitPerOperation))
{
set_time_limit($iPreviousTimeLimit);
}
return $aErrorsAndFixes;
}
@@ -317,6 +309,33 @@ class DatabaseAnalyzer
$this->ExecQuery($sSelWrongRecs, $sFixItRequest, Dict::Format('DBAnalyzer-Integrity-OrphanRecord', $sRootTable, $sTable), $sRootClass, $aErrorsAndFixes);
}
/**
* Check that the "finalclass" field is correct for all the classes of the hierarchy
*
* @param $sRootClass
* @param $sClass
* @param $sRootTable
* @param $sRootKey
* @param $sTable
* @param $sKeyField
* @param $aErrorsAndFixes
*
* @throws \CoreException
*/
private function CheckIntermediateFinalClass($sRootClass, $sClass, $sRootTable, $sRootKey, $sTable, $sKeyField, &$aErrorsAndFixes)
{
$sField = MetaModel::DBGetClassField($sClass);
$sRootField = MetaModel::DBGetClassField($sRootClass);
$sSelWrongRecs = <<<SQL
SELECT `$sTable`.`$sKeyField` AS id
FROM `$sTable`
JOIN `$sRootTable` ON `$sRootTable`.`$sRootKey` = `$sTable`.`$sKeyField`
WHERE `$sTable`.`$sField` != `$sRootTable`.`$sRootField`
SQL;
// Copy the finalclass of the root table
$sFixItRequest = "UPDATE `$sTable`,`$sRootTable` SET `$sTable`.`$sField` = `$sRootTable`.`$sRootField` WHERE `$sTable`.`$sKeyField` = `$sRootTable`.`$sRootKey`";
$this->ExecQuery($sSelWrongRecs, $sFixItRequest, Dict::Format('DBAnalyzer-Integrity-FinalClass', $sField, $sTable, $sRootTable), $sClass, $aErrorsAndFixes);
}
/**
* Check that any external field is pointing to an existing object
*
@@ -455,6 +474,8 @@ class DatabaseAnalyzer
}
/**
* Check user accounts without profile
*
* @param $aErrorsAndFixes
*
* @throws \CoreException
@@ -462,7 +483,6 @@ class DatabaseAnalyzer
*/
private function CheckUsers(&$aErrorsAndFixes)
{
// Check user accounts without profile
$sUserTable = MetaModel::DBGetTable('User');
$sLinkTable = MetaModel::DBGetTable('URP_UserProfile');
$sSelect = "SELECT DISTINCT u.id AS id, u.`login` AS value";

View File

@@ -52,6 +52,8 @@ Dict::Add('EN US', 'English', 'English', array(
'DBAnalyzer-Integrity-InvalidValue' => 'Invalid value for %1$s (column: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Some user accounts have no profile at all',
'DBAnalyzer-Fetch-Count-Error' => 'Fetch count error in `%1$s`, %2$d entries fetched / %3$d counted',
'DBAnalyzer-Integrity-FinalClass' => 'Field `%2$s`.`%1$s` must have the same value than `%3$s`.`%1$s`',
'DBAnalyzer-Integrity-RootFinalClass' => 'Field `%2$s`.`%1$s` must contains a valid class',
));
// Database Info

View File

@@ -47,6 +47,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
'DBAnalyzer-Integrity-InvalidValue' => 'Valeur invalide pour %1$s (colonne: `%2$s.%3$s`)',
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Certains comptes utilisateurs n\'ont aucun profile',
'DBAnalyzer-Fetch-Count-Error' => 'Erreur de récupération dans `%1$s`, %2$d enregistrements récupérés / %3$d comptés',
'DBAnalyzer-Integrity-FinalClass' => 'Le champ `%2$s`.`%1$s` doit avoir la même valeur que `%3$s`.`%1$s`',
'DBAnalyzer-Integrity-RootFinalClass' => 'Le champ `%2$s`.`%1$s` doit contenir une classe valide',
));
// Database Info

View File

@@ -62,6 +62,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:Attachment/Attribute:contents+' => '',
));
Dict::Add('DE DE', 'German', 'Deutsch', array(
'Attachments:File:Thumbnail' => 'Icon',
'Attachments:File:Name' => 'Dateiname',
@@ -81,4 +82,4 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Class:Attachment/Attribute:user_id+' => '',
'Class:Attachment/Attribute:contact_id' => 'Kontakt ID',
'Class:Attachment/Attribute:contact_id+' => '',
));
));

View File

@@ -1890,7 +1890,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
'Server:otherinfo' => 'Other information~~',
'Server:power' => 'Power supply~~',
'Person:info' => 'General information~~',
'UserLocal:info' => 'General information~~',
'UserLocal:info' => 'General information~~',
'Person:personal_info' => 'Personal information~~',
'Person:notifiy' => 'Notification~~',
'Class:Subnet/Tab:IPUsage' => 'Utilizzo IP',

View File

@@ -1902,7 +1902,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'Server:otherinfo' => 'Andere informatie',
'Server:power' => 'Stroomtoevoer',
'Person:info' => 'Globale informatie',
'UserLocal:info' => 'Globale informatie~~',
'UserLocal:info' => 'Globale informatie',
'Person:personal_info' => 'Persoonlijke informatie',
'Person:notifiy' => 'Notificeer',
'Class:Subnet/Tab:IPUsage' => 'IP-gebruik',

View File

@@ -20,28 +20,29 @@
* You should have received a copy of the GNU Affero General Public License
* along with iTop. If not, see <http://www.gnu.org/licenses/>
*/
Dict::Add('DE DE', 'German', 'Deutsch', array(
'iTopUpdate:UI:PageTitle' => 'Anwendungsupgrade',
'itop-core-update:UI:SelectUpdateFile' => 'Upgrade-Datei hochladen',
'itop-core-update:UI:ConfirmUpdate' => 'Confirm Upgrade',
'itop-core-update:UI:UpdateCoreFiles' => 'Upgrade der iTop-Core-Dateien',
'iTopUpdate:UI:MaintenanceModeActive' => 'Die Anwendung läuft im Wartungsmodus, Benutzerzugriffe sind nicht möglich. Führen sie erneut ein Setup oder Restore der Anwendung aus, um in den normalen Betriebsmodus zurückzukehren.',
'itop-core-update:UI:UpdateDone' => 'Upgrade abgeschlossen',
'iTopUpdate:UI:MaintenanceModeActive' => 'Die Anwendung läuft im Wartungsmodus, Benutzerzugriffe sind nicht möglich. Führen sie erneut ein Setup oder Restore der Anwendung aus, um in den normalen Betriebsmodus zurückzukehren.',
'itop-core-update:UI:UpdateDone' => 'Upgrade abgeschlossen',
'itop-core-update/Operation:SelectUpdateFile/Title' => 'Upgrade',
'itop-core-update/Operation:ConfirmUpdate/Title' => 'Upgrade bestätigen',
'itop-core-update/Operation:UpdateCoreFiles/Title' => 'Anwendungsupgrade',
'itop-core-update/Operation:SelectUpdateFile/Title' => 'Upgrade',
'itop-core-update/Operation:ConfirmUpdate/Title' => 'Upgrade bestätigen',
'itop-core-update/Operation:UpdateCoreFiles/Title' => 'Anwendungsupgrade',
'itop-core-update/Operation:UpdateDone/Title' => 'Application Upgrade Done~~',
'iTopUpdate:UI:SelectUpdateFile' => 'Upgrade-Datei hochladen',
'iTopUpdate:UI:CheckUpdate' => 'Upgrade-Datei überprüfen',
'iTopUpdate:UI:ConfirmInstallFile' => 'Installation von %1$s',
'iTopUpdate:UI:DoUpdate' => 'Upgrade',
'iTopUpdate:UI:CurrentVersion' => 'Installierte Version',
'iTopUpdate:UI:NewVersion' => 'Newly installed version~~',
'iTopUpdate:UI:Back' => 'Zurück',
'iTopUpdate:UI:Cancel' => 'Abbrechen',
'iTopUpdate:UI:Continue' => 'Weiter',
'iTopUpdate:UI:RunSetup' => 'Setuplauf',
'iTopUpdate:UI:RunSetup' => 'Setuplauf',
'iTopUpdate:UI:WithDBBackup' => 'Datenbankbackup',
'iTopUpdate:UI:WithFilesBackup' => 'Backup der Anwendungsdateien',
'iTopUpdate:UI:WithoutBackup' => 'Kein geplantes Backup',
@@ -49,7 +50,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'iTopUpdate:UI:DoFilesArchive' => 'Anwendungsdateien archivieren',
'iTopUpdate:UI:UploadArchive' => 'Archivpaket hochladen',
'iTopUpdate:UI:ServerFile' => 'Pfad zu Archivpaket, dass bereits auf dem Server liegt',
'iTopUpdate:UI:WarningReadOnlyDuringUpdate' => 'Während des Upgrades läuft die Anwendung im read-only Modus',
'iTopUpdate:UI:WarningReadOnlyDuringUpdate' => 'Während des Upgrades läuft die Anwendung im read-only Modus',
'iTopUpdate:UI:Status' => 'Status',
'iTopUpdate:UI:Action' => 'Update',
@@ -80,9 +81,9 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'iTopUpdate:UI:SetupMessage:Backup' => 'Datenbankbackup',
'iTopUpdate:UI:SetupMessage:FilesArchive' => 'Archivierung der Anwendungsdaten',
'iTopUpdate:UI:SetupMessage:CopyFiles' => 'Kopieren neuer Dateien',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Prüfung des Anwendungsupgrades',
'iTopUpdate:UI:SetupMessage:Compile' => 'Upgrade von Anwendung und Datenbank',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Upgrade Datenbank',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Prüfung des Anwendungsupgrades',
'iTopUpdate:UI:SetupMessage:Compile' => 'Upgrade von Anwendung und Datenbank',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Upgrade Datenbank',
'iTopUpdate:UI:SetupMessage:ExitMaintenance' => 'Wartungsmodus deaktivert',
'iTopUpdate:UI:SetupMessage:UpdateDone' => 'Upgrade abgeschlossen',

View File

@@ -39,8 +39,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'iTopUpdate:UI:CheckUpdate' => 'Verifieer upgrade-bestand',
'iTopUpdate:UI:ConfirmInstallFile' => 'Er zal een upgrade uitgevoerd worden met %1$s',
'iTopUpdate:UI:DoUpdate' => 'Upgrade',
'iTopUpdate:UI:CurrentVersion' => 'Versienummer huidige installatie',
'iTopUpdate:UI:NewVersion' => 'Newly installed version~~',
'iTopUpdate:UI:CurrentVersion' => 'Huidige versie',
'iTopUpdate:UI:NewVersion' => 'Nieuwe versie',
'iTopUpdate:UI:Back' => 'Vorige',
'iTopUpdate:UI:Cancel' => 'Annuleer',
'iTopUpdate:UI:Continue' => 'Volgende',
@@ -83,7 +83,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
'iTopUpdate:UI:SetupMessage:Backup' => 'Maken van backup database',
'iTopUpdate:UI:SetupMessage:FilesArchive' => 'Archiveren van de toepassingsbestanden',
'iTopUpdate:UI:SetupMessage:CopyFiles' => 'Kopiëren van nieuwe versies van bestanden',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Check application upgrade~~',
'iTopUpdate:UI:SetupMessage:CheckCompile' => 'Controleren van de upgrade van de toepassing',
'iTopUpdate:UI:SetupMessage:Compile' => 'Upgraden van toepassing en database',
'iTopUpdate:UI:SetupMessage:UpdateDatabase' => 'Upgraden van database',
'iTopUpdate:UI:SetupMessage:ExitMaintenance' => 'Deactiveren van onderhoudsmode',

View File

@@ -1,3 +1,3 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design version="1.7">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
</itop_design>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<classes>
<class id="Ticket">
<methods>

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design version="1.7">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<constants>
</constants>
<classes>

View File

@@ -16,7 +16,6 @@
*
* You should have received a copy of the GNU Affero General Public License
*/
// Portal
Dict::Add('DE DE', 'German', 'Deutsch', array(
'Page:DefaultTitle' => '%1$s - Benutzer Portal',
@@ -126,7 +125,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
'Brick:Portal:Object:Form:View:Title' => '%1$s : %2$s',
'Brick:Portal:Object:Form:Stimulus:Title' => 'Bitte folgende Informationen eintragen:',
'Brick:Portal:Object:Form:Message:Saved' => 'gespeichert',
'Brick:Portal:Object:Form:Message:ObjectSaved' => '%1$s gespeichert',
'Brick:Portal:Object:Form:Message:ObjectSaved' => '%1$s gespeichert',
'Brick:Portal:Object:Search:Regular:Title' => 'Select %1$s (%2$s)',
'Brick:Portal:Object:Search:Hierarchy:Title' => 'Select %1$s (%2$s)',
'Brick:Portal:Object:Copy:TextToCopy' => '%1$s: %2$s',

View File

@@ -80,8 +80,6 @@ class ObjectFormManager extends FormManager
protected $aFormProperties;
/** @var array $aCallbackUrls */
protected $aCallbackUrls = array();
/** @var boolean $bIsSubmittable */
protected $bIsSubmittable = true;
/**
* Creates an instance of \Combodo\iTop\Portal\Form\ObjectFormManager from JSON data that must contain at least :
@@ -222,29 +220,7 @@ class ObjectFormManager extends FormManager
return $this;
}
/**
*
* @return string
*/
public function GetIsSubmittable()
{
return $this->bIsSubmittable;
}
/**
*
* @param boolean $bIsSubmittable
*
* @return $this
*/
public function SetIsSubmittable($bIsSubmittable)
{
$this->bIsSubmittable = $bIsSubmittable;
return $this;
}
/**
*
* @return string
@@ -663,8 +639,7 @@ class ObjectFormManager extends FormManager
// Failsafe for AttributeType that would not have MakeFormField and therefore could not be used in a form
if ($oField !== null)
{
// If a form is in edit mode and can't be submitted to update an object (only transitions available), we have no reason to allow fields to be editable
if ($this->sMode !== static::ENUM_MODE_VIEW && $this->GetIsSubmittable())
if ($this->sMode !== static::ENUM_MODE_VIEW)
{
// Field dependencies
$aFieldDependencies = $oAttDef->GetPrerequisiteAttributes();

View File

@@ -277,8 +277,7 @@ class ObjectFormHandlerHelper
->SetMode($sMode)
->SetActionRulesToken($sActionRulesToken)
->SetRenderer($oFormRenderer)
->SetFormProperties($aFormProperties)
->SetIsSubmittable(isset($aFormData['buttons']['submit']) || ($sMode === self::ENUM_MODE_CREATE));
->SetFormProperties($aFormProperties);
$oFormManager->Build();

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design version="1.7">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<portals>
<portal id="itop-portal" _delta="define"><!-- ID must match module_design[id] -->
<url>pages/exec.php?exec_module=itop-portal-base&amp;exec_page=index.php&amp;portal_id=itop-portal</url><!-- portal_id must match module_design[id] -->

View File

@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<itop_design version="1.6">
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.7">
<classes/>
<user_rights>
<groups>

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8"?>
<information>
<version>2.7.0-beta2</version>
<version>2.7.0</version>
</information>