mirror of
https://github.com/Combodo/iTop.git
synced 2026-07-28 09:36:49 +02:00
Compare commits
30 Commits
faf/data_t
...
3.3.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c6e50a0ed7 | ||
|
|
76a410e00d | ||
|
|
c68887c2bc | ||
|
|
837b433622 | ||
|
|
52fca750b0 | ||
|
|
d1aedee245 | ||
|
|
85d50f31bd | ||
|
|
3c301affb3 | ||
|
|
147fae7f8c | ||
|
|
a5aa8c279f | ||
|
|
04f91ab4a2 | ||
|
|
8e0246601a | ||
|
|
e6cdcd0a5a | ||
|
|
2ab3081926 | ||
|
|
5cabac63e7 | ||
|
|
3918dcf830 | ||
|
|
489300552a | ||
|
|
8507c606ba | ||
|
|
128989450b | ||
|
|
1bd404af6f | ||
|
|
6c770d3e16 | ||
|
|
a74dbb3a73 | ||
|
|
b365aa0971 | ||
|
|
56aa50c9b1 | ||
|
|
eacb7f3401 | ||
|
|
b14045af29 | ||
|
|
7321eeb23f | ||
|
|
05b8c529fe | ||
|
|
a68c017225 | ||
|
|
82b52b95a1 |
0
.make/license/gen-community-license.sh
Normal file → Executable file
0
.make/license/gen-community-license.sh
Normal file → Executable file
0
.make/license/sortLicenceXml.php
Normal file → Executable file
0
.make/license/sortLicenceXml.php
Normal file → Executable file
0
.make/license/updateLicenses.php
Normal file → Executable file
0
.make/license/updateLicenses.php
Normal file → Executable file
0
.make/release/changelog.php
Normal file → Executable file
0
.make/release/changelog.php
Normal file → Executable file
0
.make/release/update-versions.php
Normal file → Executable file
0
.make/release/update-versions.php
Normal file → Executable file
0
.make/release/update-xml.php
Normal file → Executable file
0
.make/release/update-xml.php
Normal file → Executable file
0
.make/release/update.classes.inc.php
Normal file → Executable file
0
.make/release/update.classes.inc.php
Normal file → Executable file
@@ -5368,7 +5368,6 @@ JS
|
||||
/**
|
||||
* @param array $aChanges
|
||||
* @param bool $bIsNew
|
||||
* @param string|null $sStimulusBeingApplied
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
@@ -5382,20 +5381,6 @@ JS
|
||||
$this->FireEvent(EVENT_DB_AFTER_WRITE, ['is_new' => $bIsNew, 'changes' => $aChanges, 'stimulus_applied' => $sStimulusBeingApplied, 'cmdb_change' => self::GetCurrentChange()]);
|
||||
}
|
||||
|
||||
//////////////
|
||||
/// READ
|
||||
///
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @throws \CoreException
|
||||
* @since 3.3.0
|
||||
*/
|
||||
final public function FireEventReadDetails(string $sExportType): void
|
||||
{
|
||||
$this->FireEvent(EVENT_DATA_EXPORT, ['export_type' => $sExportType]);
|
||||
}
|
||||
|
||||
//////////////
|
||||
/// DELETE
|
||||
///
|
||||
|
||||
@@ -519,31 +519,6 @@ Call $this->AddInitialAttributeFlags($sAttCode, $iFlags) for all the initial att
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DATA_EXPORT" _delta="define">
|
||||
<name>Object details read from outside iTop</name>
|
||||
<description><![CDATA[An object details has been read during an export]]></description>
|
||||
<sources>
|
||||
<source id="cmdbAbstractObject">cmdbAbstractObject</source>
|
||||
</sources>
|
||||
<event_data>
|
||||
<event_datum id="object">
|
||||
<description>The object unarchived</description>
|
||||
<type>DBObject</type>
|
||||
</event_datum>
|
||||
<event_datum id="attributes">
|
||||
<description>Attribute codes exposed (empty means potentially all attributes)</description>
|
||||
<type>array</type>
|
||||
</event_datum>
|
||||
<event_datum id="export_type">
|
||||
<description>Type of export</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
<event_datum id="debug_info">
|
||||
<description>Debug string</description>
|
||||
<type>string</type>
|
||||
</event_datum>
|
||||
</event_data>
|
||||
</event>
|
||||
<event id="EVENT_DOWNLOAD_DOCUMENT" _delta="define">
|
||||
<name>Document downloaded</name>
|
||||
<description><![CDATA[A document has been downloaded from the GUI]]></description>
|
||||
|
||||
@@ -334,14 +334,12 @@ EOF
|
||||
while ($aRow = $oSet->FetchAssoc()) {
|
||||
set_time_limit(intval($iLoopTimeLimit));
|
||||
$aData = [];
|
||||
$aExportedObjects = [];
|
||||
foreach ($this->aStatusInfo['fields'] as $aFieldSpec) {
|
||||
foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
|
||||
$sAlias = $aFieldSpec['sAlias'];
|
||||
$sAttCode = $aFieldSpec['sAttCode'];
|
||||
|
||||
$sField = '';
|
||||
$oObj = $aRow[$sAlias];
|
||||
$aExportedObjects[] = $oObj;
|
||||
if ($oObj != null) {
|
||||
switch ($sAttCode) {
|
||||
case 'id':
|
||||
@@ -368,13 +366,7 @@ EOF
|
||||
}
|
||||
$sData .= implode($this->aStatusInfo['separator'], $aData)."\n";
|
||||
$iCount++;
|
||||
|
||||
$aExportedObjects = array_unique($aExportedObjects);
|
||||
foreach ($aExportedObjects as $oExportedObject) {
|
||||
$oExportedObject->FireEventReadDetails(get_class($this));
|
||||
}
|
||||
}
|
||||
|
||||
// Restore original date & time formats
|
||||
AttributeDateTime::SetFormat($oPrevDateTimeFormat);
|
||||
AttributeDate::SetFormat($oPrevDateFormat);
|
||||
|
||||
@@ -6247,9 +6247,7 @@ abstract class DBObject implements iDisplay
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aChanges
|
||||
* @param bool $bIsNew
|
||||
* @param string|null $sStimulusBeingApplied
|
||||
*
|
||||
* @return void
|
||||
* @since 3.1.0
|
||||
@@ -6258,18 +6256,6 @@ abstract class DBObject implements iDisplay
|
||||
{
|
||||
}
|
||||
|
||||
//////////////
|
||||
/// READ
|
||||
///
|
||||
|
||||
/**
|
||||
* @return void
|
||||
* @since 3.3.0
|
||||
*/
|
||||
public function FireEventReadDetails(string $sExportType): void
|
||||
{
|
||||
}
|
||||
|
||||
//////////////
|
||||
/// DELETE
|
||||
///
|
||||
|
||||
@@ -288,13 +288,11 @@ EOF
|
||||
while ($aRow = $oSet->FetchAssoc()) {
|
||||
set_time_limit(intval($iLoopTimeLimit));
|
||||
$aData = [];
|
||||
$aExportedObjects = [];
|
||||
foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
|
||||
$sAlias = $aFieldSpec['sAlias'];
|
||||
$sAttCode = $aFieldSpec['sAttCode'];
|
||||
|
||||
$oObj = $aRow[$sAlias];
|
||||
$aExportedObjects[] = $oObj;
|
||||
$sField = '';
|
||||
if ($oObj) {
|
||||
$sField = $this->GetValue($oObj, $sAttCode);
|
||||
@@ -303,11 +301,6 @@ EOF
|
||||
}
|
||||
fwrite($hFile, json_encode($aData)."\n");
|
||||
$iCount++;
|
||||
|
||||
$aExportedObjects = array_unique($aExportedObjects);
|
||||
foreach ($aExportedObjects as $oExportedObject) {
|
||||
$oExportedObject->FireEventReadDetails(get_class($this));
|
||||
}
|
||||
}
|
||||
set_time_limit(intval($iPreviousTimeLimit));
|
||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||
|
||||
@@ -139,7 +139,6 @@ class HTMLBulkExport extends TabularBulkExport
|
||||
} else {
|
||||
$sData .= "<tr>";
|
||||
}
|
||||
$aExportedObjects = [];
|
||||
foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
|
||||
$sAlias = $aFieldSpec['sAlias'];
|
||||
$sAttCode = $aFieldSpec['sAttCode'];
|
||||
@@ -148,18 +147,12 @@ class HTMLBulkExport extends TabularBulkExport
|
||||
$sField = '';
|
||||
if ($oObj) {
|
||||
$sField = $this->GetValue($oObj, $sAttCode);
|
||||
$aExportedObjects[] = $oObj;
|
||||
}
|
||||
$sValue = ($sField === '') ? ' ' : $sField;
|
||||
$sData .= "<td>$sValue</td>";
|
||||
}
|
||||
$sData .= "</tr>";
|
||||
$iCount++;
|
||||
|
||||
$aExportedObjects = array_unique($aExportedObjects);
|
||||
foreach ($aExportedObjects as $oExportedObject) {
|
||||
$oExportedObject->FireEventReadDetails(get_class($this));
|
||||
}
|
||||
}
|
||||
set_time_limit(intval($iPreviousTimeLimit));
|
||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||
|
||||
@@ -625,7 +625,6 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
|
||||
}
|
||||
|
||||
while ($oObject = $oObjectSet->Fetch()) {
|
||||
$oObject->FireEventReadDetails(get_class($this));
|
||||
$oResult->AddObject(0, '', $oObject, $aShowFields, RestUtils::HasRequestedExtendedOutput($sShowFields));
|
||||
}
|
||||
$oResult->message = "Found: ".$oObjectSet->Count();
|
||||
@@ -700,7 +699,6 @@ class CoreServices implements iRestServiceProvider, iRestInputSanitizer
|
||||
if ($oElement instanceof RelationObjectNode) {
|
||||
$oObject = $oElement->GetProperty('object');
|
||||
if ($oObject) {
|
||||
$oObject->FireEventReadDetails(get_class($this));
|
||||
if ($bEnableRedundancy && $sDirection == 'down') {
|
||||
// Add only the "reached" objects
|
||||
if ($oElement->GetProperty('is_reached')) {
|
||||
|
||||
@@ -233,6 +233,7 @@ EOF
|
||||
public function GetNextChunk(&$aStatus)
|
||||
{
|
||||
$sRetCode = 'run';
|
||||
$iPercentage = 0;
|
||||
|
||||
$oSet = new DBObjectSet($this->oSearch);
|
||||
$oSet->SetLimit($this->iChunkSize, $this->aStatusInfo['position']);
|
||||
@@ -253,8 +254,7 @@ EOF
|
||||
set_time_limit(intval($iLoopTimeLimit));
|
||||
|
||||
$sData .= "<tr>";
|
||||
$aExportedObjects = [];
|
||||
foreach ($this->aStatusInfo['fields'] as $aFieldSpec) {
|
||||
foreach ($this->aStatusInfo['fields'] as $iCol => $aFieldSpec) {
|
||||
$sAlias = $aFieldSpec['sAlias'];
|
||||
$sAttCode = $aFieldSpec['sAttCode'];
|
||||
|
||||
@@ -265,7 +265,7 @@ EOF
|
||||
$sData .= "<td x:str></td>";
|
||||
continue;
|
||||
}
|
||||
$aExportedObjects[] = $oObj;
|
||||
|
||||
switch ($sAttCode) {
|
||||
case 'id':
|
||||
$sField = $oObj->GetKey();
|
||||
@@ -322,11 +322,6 @@ EOF
|
||||
}
|
||||
$sData .= "</tr>";
|
||||
$iCount++;
|
||||
|
||||
$aExportedObjects = array_unique($aExportedObjects);
|
||||
foreach ($aExportedObjects as $oExportedObject) {
|
||||
$oExportedObject->FireEventReadDetails(get_class($this));
|
||||
}
|
||||
}
|
||||
set_time_limit(intval($iPreviousTimeLimit));
|
||||
$this->aStatusInfo['position'] += $this->iChunkSize;
|
||||
|
||||
@@ -135,11 +135,6 @@ abstract class Trigger extends cmdbAbstractObject
|
||||
if ($oAction->IsActive()) {
|
||||
$oKPI = new ExecutionKPI();
|
||||
$aContextArgs['action->object()'] = $oAction;
|
||||
if (array_key_exists('this->object()', $aContextArgs)) {
|
||||
/** @var \DBObject $oObject */
|
||||
$oObject = $aContextArgs['this->object()'];
|
||||
$oObject->FireEventReadDetails(get_class($oAction));
|
||||
}
|
||||
$oAction->DoExecute($this, $aContextArgs);
|
||||
$oKPI->ComputeStatsForExtension($oAction, 'DoExecute');
|
||||
}
|
||||
|
||||
@@ -144,7 +144,6 @@ class XMLBulkExport extends BulkExport
|
||||
if (count($aAuthorizedClasses) > 1) {
|
||||
$sData .= "<Row>\n";
|
||||
}
|
||||
$aExportedObjects = [];
|
||||
foreach ($aAuthorizedClasses as $sAlias => $sClassName) {
|
||||
$oObj = $aObjects[$sAlias];
|
||||
if (is_null($oObj)) {
|
||||
@@ -152,7 +151,6 @@ class XMLBulkExport extends BulkExport
|
||||
} else {
|
||||
$sClassName = get_class($oObj);
|
||||
$sData .= "<$sClassName alias=\"$sAlias\" id=\"".$oObj->GetKey()."\">\n";
|
||||
$aExportedObjects[] = $oObj;
|
||||
}
|
||||
foreach ($aClass2Attributes[$sAlias] as $sAttCode => $oAttDef) {
|
||||
if (is_null($oObj)) {
|
||||
@@ -168,11 +166,6 @@ class XMLBulkExport extends BulkExport
|
||||
$sData .= "</Row>\n";
|
||||
}
|
||||
$iCount++;
|
||||
|
||||
$aExportedObjects = array_unique($aExportedObjects);
|
||||
foreach ($aExportedObjects as $oExportedObject) {
|
||||
$oExportedObject->FireEventReadDetails(get_class($this));
|
||||
}
|
||||
}
|
||||
|
||||
set_time_limit(intval($iPreviousTimeLimit));
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*/
|
||||
|
||||
/* SCSS variables */
|
||||
$common-has-description--content: "\1F6C8" !default;
|
||||
$common-has-description--content: "?" !default;
|
||||
$common-has-description--padding-left: $common-spacing-200 !default;
|
||||
$common-has-description--color: $common-color-grey-600 !default;
|
||||
$common-has-description--font-size: 0.7em !default; /* Font size is em on purpose as we want it to be proportional to its context */
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
*
|
||||
* Usage: @extend %common-font-size-XXX;
|
||||
*/
|
||||
%common-font-size-20 {
|
||||
font-size: $common-font-size-20;
|
||||
}
|
||||
%common-font-size-50 {
|
||||
font-size: $common-font-size-50;
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -127,6 +127,9 @@ class DataFeatureRemovalController extends Controller
|
||||
|
||||
$aRemovedExtensions = $this->aExtensionsToCheck['to_be_removed'];
|
||||
$aHiddenInputs['removed_extensions'] = $this->ConvertIntoSetupFormat($aRemovedExtensions);
|
||||
|
||||
$aExtensionsNotUninstallable = $this->aExtensionsToCheck['extensions_not_uninstallable'];
|
||||
$aHiddenInputs['extensions_not_uninstallable'] = $this->ConvertIntoSetupFormat($aExtensionsNotUninstallable);
|
||||
}
|
||||
|
||||
$aParams['aAddedExtensions'] = $aAddedExtensions;
|
||||
@@ -344,7 +347,7 @@ class DataFeatureRemovalController extends Controller
|
||||
'uninstallable' => $oExtension->CanBeUninstalled(),
|
||||
'remote' => $oExtension->IsRemote(),
|
||||
'missing' => $oExtension->bRemovedFromDisk,
|
||||
'cannot-be-installed' => (!$oExtension->bInstalled && count($oExtension->aMissingDependencies) > 0),
|
||||
'dependency_issue' => $oExtension->HasDependencyIssue(),
|
||||
],
|
||||
|
||||
];
|
||||
@@ -425,6 +428,7 @@ class DataFeatureRemovalController extends Controller
|
||||
$this->aExtensionsToCheck = [
|
||||
'to_be_installed' => [],
|
||||
'to_be_removed' => [],
|
||||
'extensions_not_uninstallable' => [],
|
||||
];
|
||||
foreach ($aAvailableExtensions as $sCode => &$aExtensionData) {
|
||||
if (!isset($aSelectedExtensionsFromUI[$sCode])) {
|
||||
@@ -438,6 +442,9 @@ class DataFeatureRemovalController extends Controller
|
||||
if (! $this->bForcedUninstallation && $aExtensionData['extra_flags']['uninstallable']) {
|
||||
$this->bForcedUninstallation = true;
|
||||
}
|
||||
if (false === $aExtensionData['extra_flags']['uninstallable'] || true === $aExtensionData['extra_flags']['remote']) {
|
||||
$this->aExtensionsToCheck['extensions_not_uninstallable'][] = $sCode;
|
||||
}
|
||||
} elseif (!$aExtensionData['installed'] && $aSelectedExtensionsFromUI[$sCode] === 'on') {
|
||||
$aExtensionData['extra_flags']['selected'] = true;
|
||||
$sLabel = $aAvailableExtensions[$sCode]['label'];
|
||||
|
||||
@@ -134,10 +134,6 @@ class DataCleanupService
|
||||
/** @var DBObject $oDependentObj */
|
||||
while ($oDependentObj = $oSet->Fetch()) {
|
||||
$iDeletePropagationOption = $oExtKeyAttDef->GetDeletionPropagationOption();
|
||||
if ($iDeletePropagationOption == DEL_MANUAL) {
|
||||
$this->oObjectService->SetIssue(get_class($oDependentObj));
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($oExtKeyAttDef->IsNullAllowed()) {
|
||||
// Optional external key, list to reset
|
||||
@@ -152,6 +148,12 @@ class DataCleanupService
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// Mandatory external key
|
||||
if ($iDeletePropagationOption == DEL_MANUAL) {
|
||||
// Cannot be deleted automatically, must be handled manually
|
||||
$this->oObjectService->SetIssue(get_class($oDependentObj));
|
||||
continue;
|
||||
}
|
||||
// Propagate deletion only if not visited
|
||||
if ($this->IsVisited($oDependentObj)) {
|
||||
continue;
|
||||
|
||||
@@ -59,9 +59,11 @@ class StaticDeletionPlan
|
||||
{
|
||||
foreach ($aClasses as $sClass) {
|
||||
$oDeletionPlanItem = $this->GetInitialClassDeletionPlan($sClass);
|
||||
$oDeletionPlanEntity = new DeletionPlanEntity();
|
||||
$oDeletionPlanEntity->oDelete->Merge($oDeletionPlanItem);
|
||||
$this->aDeletionPlan[$sClass] = $oDeletionPlanEntity;
|
||||
// N°9831 Do not overwrite existing entity as it may already exist for this class if a previously processed class references it (issues/updates already accumulated must be kept)
|
||||
if (false === array_key_exists($sClass, $this->aDeletionPlan)) {
|
||||
$this->aDeletionPlan[$sClass] = new DeletionPlanEntity();
|
||||
}
|
||||
$this->aDeletionPlan[$sClass]->oDelete->Merge($oDeletionPlanItem);
|
||||
|
||||
$this->DeletionPlanForReferencingClasses($sClass);
|
||||
}
|
||||
|
||||
@@ -90,6 +90,6 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:TriggerOnAttachmentDelete' => 'Déclencheur sur la suppression d\'une pièce jointe',
|
||||
'Class:TriggerOnAttachmentDelete+' => 'Déclencheur sur la suppression d\'une pièce jointe d\'un objet',
|
||||
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email' => 'Ajoute le fichier supprimé dans l\'email',
|
||||
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => 'If checked, the deleted file will be automatically attached to the email when an email action is triggered~~',
|
||||
'Class:TriggerOnAttachmentDelete/Attribute:file_in_email+' => 'Si coché, le fichier supprimé sera automatiquement joint à l\'email quand une action email sera lancée',
|
||||
'Class:TriggerOnObject:TriggerClassAttachment/ReadOnlyMessage' => 'Les Triggers sur les objets ne sont pas autorisés sur la classe Attachement. Veuillez utiliser les triggers spécifiques pour cette classe',
|
||||
]);
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<NetworkDeviceType alias="NetworkDeviceType" id="10">
|
||||
<name>Router</name>
|
||||
</NetworkDeviceType>
|
||||
<NetworkDeviceType alias="NetworkDeviceType" id="11">
|
||||
<name>Switch</name>
|
||||
</NetworkDeviceType>
|
||||
</Set>
|
||||
@@ -32,7 +32,6 @@ SetupWebPage::AddModule(
|
||||
],
|
||||
'data.sample' => [
|
||||
'data/data.sample.model.xml',
|
||||
'data/data.sample.networkdevicetype.xml',
|
||||
'data/data.sample.servers.xml',
|
||||
'data/data.sample.nw-devices.xml',
|
||||
'data/data.sample.software.xml',
|
||||
@@ -106,6 +105,7 @@ if (!class_exists('ConfigMgmtInstaller')) {
|
||||
*/
|
||||
public static function AfterDatabaseCreation(Config $oConfiguration, $sPreviousVersion, $sCurrentVersion)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +159,7 @@ function DoInstall(WebPage $oPage)
|
||||
|
||||
foreach ($oExtensionsMap->GetAllExtensions() as $oExtension) {
|
||||
if ($oExtension->sSource == iTopExtension::SOURCE_REMOTE) {
|
||||
if (count($oExtension->aMissingDependencies) > 0) {
|
||||
if ($oExtension->HasDependencyIssue()) {
|
||||
$oPage->add('<div class="choice">');
|
||||
$oPage->add('<input type="checkbox" disabled> ');
|
||||
$sTitle = Dict::Format('iTopHub:InstallationEffect:MissingDependencies_Details', implode(', ', $oExtension->aMissingDependencies));
|
||||
|
||||
@@ -50,13 +50,13 @@ const oOpenSignInWindow = function (url, name) {
|
||||
then we load it in the already opened secondary window, and then
|
||||
we bring such window back on top/in front of its parent window. */
|
||||
oWindowObjectReference = window.open(url, name, sWindowFeatures);
|
||||
oWindowObjectReference.trigger('focus');
|
||||
oWindowObjectReference.focus();
|
||||
} else {
|
||||
/* Else the window reference must exist and the window
|
||||
is not closed; therefore, we can bring it back on top of any other
|
||||
window with the focus() method. There would be no need to re-create
|
||||
the window or to reload the referenced resource. */
|
||||
oWindowObjectReference.trigger('focus');
|
||||
oWindowObjectReference.focus();
|
||||
}
|
||||
/* Let know every second our child window that we're waiting for it to complete,
|
||||
once we reach our landing page, it'll send us a reply
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -36,7 +36,7 @@ $ipb-field--is-mandatory--font-size: 0.6rem !default;
|
||||
|
||||
.form_field_label > .control-label[data-tooltip-instantiated="true"]:after {
|
||||
cursor: pointer;
|
||||
@extend %common-font-size-50;
|
||||
@extend %common-font-size-20;
|
||||
}
|
||||
|
||||
.form_field .form_mandatory .control-label:after{
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -10,7 +10,7 @@ $ipb--fieldset--border: 1px solid $ipb--fieldset--border-color !default;
|
||||
|
||||
$ipb--fieldset--inside--fieldset--background-color: $ipb-color-grey-100 !default;
|
||||
|
||||
$ipb-field--has-tooltip--content: "\f05a" !default;
|
||||
$ipb-field--has-tooltip--content: "\f128" !default;
|
||||
$ipb-field--has-tooltip--color: $ipb-color-grey-700 !default;
|
||||
|
||||
$ipb-field--is-mandatory--content: "\f069" !default;
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ContractType alias="ContractType" id="78">
|
||||
<name>Hosting</name>
|
||||
</ContractType>
|
||||
<ContractType alias="ContractType" id="79">
|
||||
<name>IT-Outsourcing</name>
|
||||
</ContractType>
|
||||
<ContractType alias="ContractType" id="77">
|
||||
<name>Wartung</name>
|
||||
</ContractType>
|
||||
<ContractType alias="ContractType" id="76">
|
||||
<name>Support</name>
|
||||
</ContractType>
|
||||
</Set>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<CustomerContract alias="CustomerContract" id="3">
|
||||
<name>Kundenvertrag</name>
|
||||
<org_id>7</org_id>
|
||||
<description>Kundenvertrag zur Bereitstellung von Services fuer einen externen Kunden.</description>
|
||||
<start_date>2026-01-01</start_date>
|
||||
<end_date>2030-12-31</end_date>
|
||||
<cost>10000</cost>
|
||||
<cost_currency>euros</cost_currency>
|
||||
<contracttype_id>79</contracttype_id>
|
||||
<billing_frequency>yearly</billing_frequency>
|
||||
<provider_id>2</provider_id>
|
||||
<status>production</status>
|
||||
</CustomerContract>
|
||||
<CustomerContract alias="CustomerContract" id="1">
|
||||
<name>Kundenvertrag Vertriebsabteilung</name>
|
||||
<org_id>6</org_id>
|
||||
<description>Interner Vertrag zur Bereitstellung von Services fuer die Vertriebsabteilung</description>
|
||||
<start_date>2019-01-01</start_date>
|
||||
<end_date>2030-12-31</end_date>
|
||||
<cost>0</cost>
|
||||
<cost_currency>euros</cost_currency>
|
||||
<contracttype_id>0</contracttype_id>
|
||||
<billing_frequency>monthly</billing_frequency>
|
||||
<provider_id>2</provider_id>
|
||||
<status>production</status>
|
||||
</CustomerContract>
|
||||
</Set>
|
||||
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="28">
|
||||
<name>Zugriffsprobleme</name>
|
||||
<description>Hilfe bei einem Zugriffsproblem anfordern</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="17">
|
||||
<name>API-Integration</name>
|
||||
<description>Verbindung zwischen internen und externen Anwendungen.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="13">
|
||||
<name>CRM (z. B. Salesforce, HubSpot)</name>
|
||||
<description>Einrichtung, Anpassung und Support für das Customer-Relationship-Management.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="22">
|
||||
<name>Sensibilisierung für Cybersicherheit</name>
|
||||
<description>Schulung der Mitarbeitenden zu bewährten Praktiken (Phishing, Passwörter usw.).</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="3">
|
||||
<name>Datensicherung</name>
|
||||
<description>Automatische Sicherung kritischer Dateien (täglich/wöchentlich/monatlich).</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="21">
|
||||
<name>Datenschutz (DSGVO)</name>
|
||||
<description>Unterstützung bei der Einhaltung gesetzlicher Vorgaben (DSGVO, HIPAA usw.).</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="1">
|
||||
<name>ERP (z. B. SAP, Odoo)</name>
|
||||
<description>Zugriff, Support und Schulung für integrierte Managementsoftware.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="10">
|
||||
<name>Dateispeicherung und -freigabe</name>
|
||||
<description>Bereitstellung kollaborativer Speicherbereiche (z. B. SharePoint, Nextcloud).</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="12">
|
||||
<name>Hardwarevorfall</name>
|
||||
<description>Unterstützung bei einem Hardwareausfall anfordern.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="19">
|
||||
<name>Hardware-Upgrade</name>
|
||||
<description>Austausch oder Erweiterung von Komponenten (RAM, Festplatte usw.).</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="7">
|
||||
<name>Lokales Netzwerk (LAN/Wi-Fi)</name>
|
||||
<description>Installation, Konfiguration und Wartung von Netzwerkgeräten.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="27">
|
||||
<name>Multi-Faktor-Authentifizierung (MFA)</name>
|
||||
<description>Konfiguration und Support für Multi-Faktor-Authentifizierung.</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="4">
|
||||
<name>Fehlerbehebung im Netzwerk</name>
|
||||
<description>Hilfe bei der Behebung eines Netzwerkproblems anfordern.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="5">
|
||||
<name>Bestellung neuer Desktop-Computer</name>
|
||||
<description>Einen neuen Desktop-Computer für neue Mitarbeitende oder als Ersatz für ein altes System bestellen.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="8">
|
||||
<name>Bestellung neuer Laptops</name>
|
||||
<description>Einen neuen Laptop für mobile Mitarbeitende oder als Ersatz für ein altes Gerät bestellen.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="11">
|
||||
<name>Neues Peripheriegerät</name>
|
||||
<description>Ein Peripheriegerät bestellen: Tastatur, Maus, persönlicher Drucker ...</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="20">
|
||||
<name>Sicherheitsaudit</name>
|
||||
<description>Schwachstellenanalysen, Penetrationstests und Empfehlungen.</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="23">
|
||||
<name>Sicherheitsvorfall</name>
|
||||
<description>Reaktion auf Cyberangriffe, Datenlecks oder Sicherheitsverletzungen.</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="6">
|
||||
<name>Serververwaltung</name>
|
||||
<description>Präventive Wartung, Software-Updates und 24/7-Überwachung.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="16">
|
||||
<name>Softwarevorfall</name>
|
||||
<description>Hilfe bei der Behebung eines Softwareproblems anfordern.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="15">
|
||||
<name>Softwarevorfall</name>
|
||||
<description>Unterstützung bei einem softwarebezogenen Problem anfordern.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="18">
|
||||
<name>Softwareinstallation</name>
|
||||
<description>Bereitstellung von Office-Software (z. B. Microsoft 365, LibreOffice) und Geschäftssoftware.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="14">
|
||||
<name>Individuelle Entwicklung</name>
|
||||
<description>Entwicklung maßgeschneiderter Tools (Dashboards, Automatisierungen, Skripte).</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="24">
|
||||
<name>Benutzerkonto-Erstellung</name>
|
||||
<description>Erstellung von Konten für neue Mitarbeitende oder Auftragnehmer.</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="26">
|
||||
<name>Benutzerkonto-Löschung</name>
|
||||
<description>Deaktivierung von Konten für ausscheidende Mitarbeitende oder am Ende ihrer Verträge.</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="25">
|
||||
<name>Benutzerkonto-Aktualisierung</name>
|
||||
<description>Hinzufügen oder Entfernen von Berechtigungen (z. B. Zugriff auf einen freigegebenen Ordner oder eine Anwendung).</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="2">
|
||||
<name>VPN-Zugriff</name>
|
||||
<description>Konfiguration und Support für sicheren Fernzugriff auf interne Ressourcen.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
</Set>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ServiceFamily alias="ServiceFamily" id="1">
|
||||
<name>IT-Services</name>
|
||||
<icon>
|
||||
<mimetype>image/svg+xml</mimetype>
|
||||
<filename>icons8-open-end-wrench.svg</filename>
|
||||
<data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNDBweCIgaGVpZ2h0PSIyNDBweCI+PHJhZGlhbEdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2phIiBjeD0iOS4xNjkiIGN5PSIzOC42NyIgcj0iMTIuMTM1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuNzA2IiBzdG9wLWNvbG9yPSIjNzg3Zjg1Ii8+PHN0b3Agb2Zmc2V0PSIuNzEzIiBzdG9wLWNvbG9yPSIjN2E4MTg3Ii8+PHN0b3Agb2Zmc2V0PSIuNzkzIiBzdG9wLWNvbG9yPSIjOTA5ODlmIi8+PHN0b3Agb2Zmc2V0PSIuODY4IiBzdG9wLWNvbG9yPSIjOWRhNWFlIi8+PHN0b3Agb2Zmc2V0PSIuOTMiIHN0b3AtY29sb3I9IiNhMWFhYjMiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjMEJESnMzV3RwcE1nbzRZOUE3R2dqYSkiIGQ9Ik0xOS45MTUsMjEuOGMtNC42NzksNC42NzktOS4zNzUsOS4zNzUtOS41NTEsOS41NTFsNi4zNjQsNi4zNjQgYzAuMTc3LTAuMTc3LDQuODcyLTQuODcyLDkuNTUxLTkuNTUxTDE5LjkxNSwyMS44eiIvPjxyYWRpYWxHcmFkaWVudCBpZD0iMEJESnMzV3RwcE1nbzRZOUE3R2dqYiIgY3g9IjEzLjQyNSIgY3k9IjM1LjQ5OSIgcj0iMTQuNjg4IiBncmFkaWVudFRyYW5zZm9ybT0icm90YXRlKDE4MCAyNC4zMjIgMjMuNzU4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjcwNiIgc3RvcC1jb2xvcj0iIzc4N2Y4NSIvPjxzdG9wIG9mZnNldD0iLjcxMyIgc3RvcC1jb2xvcj0iIzdhODE4NyIvPjxzdG9wIG9mZnNldD0iLjc5MyIgc3RvcC1jb2xvcj0iIzkwOTg5ZiIvPjxzdG9wIG9mZnNldD0iLjg2OCIgc3RvcC1jb2xvcj0iIzlkYTVhZSIvPjxzdG9wIG9mZnNldD0iLjkzIiBzdG9wLWNvbG9yPSIjYTFhYWIzIi8+PC9yYWRpYWxHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoIzBCREpzM1d0cHBNZ280WTlBN0dnamIpIiBkPSJNMjQuNzI4LDI5LjcxNWM0LjY3OS00LjY3OSw5LjM3NS05LjM3NSw5LjU1MS05LjU1MUwyNy45MTUsMTMuOCBjLTAuMTc3LDAuMTc3LTQuODcyLDQuODcyLTkuNTUxLDkuNTUxTDI0LjcyOCwyOS43MTV6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2pjIiB4MT0iMjIuMTE5IiB4Mj0iMzMuOTI2IiB5MT0iLTI1NTIuODgzIiB5Mj0iLTI1NjQuNjkiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMzkuMDQ2IDI1OTguMDMzKSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzhmOTc5ZSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ExYWFiMyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCMwQkRKczNXdHBwTWdvNFk5QTdHZ2pkKSIgZD0iTTQwLjY2MiwxMy4zMTJjLTEuNjk1LDEuNjk1LTQuNDQ1LDEuNjk1LTYuMTM5LDBzLTEuNjk1LTQuNDQ1LDAtNi4xMzkgYzAuNDE0LTAuNDE0LDIuMDgxLTIuMDgxLDMuNzgtMy43OGMwLjQwNy0wLjQwNywwLjIyNi0xLjExOS0wLjMzMi0xLjI1NmMtMS4zNzctMC4zMzgtMi44NTgtMC40MDktNC4zOTktMC4xMTkgYy00LjUxOSwwLjg1Mi04LjA0Myw0LjYzMy04LjUxMiw5LjIwN2MtMC42ODQsNi42Nyw0Ljg4MywxMi4yMzYsMTEuNTUzLDExLjU1MWM0LjU3NC0wLjQ3LDguMzU1LTMuOTk0LDkuMjA2LTguNTEzIGMwLjI5LTEuNTQxLDAuMjE5LTMuMDIxLTAuMTE5LTQuMzk4Yy0wLjEzOC0wLjU2LTAuODQ5LTAuNzQxLTEuMjU2LTAuMzMyQzQyLjc0MywxMS4yMzEsNDEuMDc2LDEyLjg5OSw0MC42NjIsMTMuMzEyeiIvPjwvc3ZnPgo=</data>
|
||||
<downloads_count>0</downloads_count>
|
||||
</icon>
|
||||
</ServiceFamily>
|
||||
</Set>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<SLA alias="SLA" id="4">
|
||||
<name>SLA Bronze</name>
|
||||
<description>Service-Level-Agreement Bronze fuer Services mit niedriger Kritikalitaet</description>
|
||||
<org_id>2</org_id>
|
||||
</SLA>
|
||||
<SLA alias="SLA" id="2">
|
||||
<name>SLA Gold</name>
|
||||
<description>Service-Level-Agreement Gold fuer Services mit hoher Kritikalitaet</description>
|
||||
<org_id>2</org_id>
|
||||
</SLA>
|
||||
<SLA alias="SLA" id="3">
|
||||
<name>SLA Silver</name>
|
||||
<description>Service-Level-Agreement Silver fuer Services mit mittlerer Kritikalitaet</description>
|
||||
<org_id>2</org_id>
|
||||
</SLA>
|
||||
</Set>
|
||||
@@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<SLT alias="SLT" id="5">
|
||||
<name>TTO Vorfall Priorität kritisch 1 Stunde</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="3">
|
||||
<name>TTO Vorfall Priorität kritisch 15 Minuten</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>15</value>
|
||||
<unit>minutes</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="4">
|
||||
<name>TTO Vorfall Priorität kritisch 30 Minuten</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>30</value>
|
||||
<unit>minutes</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="7">
|
||||
<name>TTO Vorfall Priorität hoch 1 Stunde</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="8">
|
||||
<name>TTO Vorfall Priorität hoch 2 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="6">
|
||||
<name>TTO Vorfall Priorität hoch 30 Minuten</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>30</value>
|
||||
<unit>minutes</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="12">
|
||||
<name>TTO Vorfall Priorität niedrig 2 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="13">
|
||||
<name>TTO Vorfall Priorität niedrig 4 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="14">
|
||||
<name>TTO Vorfall Priorität niedrig 8 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="9">
|
||||
<name>TTO Vorfall Priorität mittel 1 Stunde</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="10">
|
||||
<name>TTO Vorfall Priorität mittel 2 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="11">
|
||||
<name>TTO Vorfall Priorität mittel 4 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="27">
|
||||
<name>TTO Serviceanfrage Priorität kritisch 1 Stunde</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="28">
|
||||
<name>TTO Serviceanfrage Priorität kritisch 2 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="29">
|
||||
<name>TTO Serviceanfrage Priorität kritisch 4 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="30">
|
||||
<name>TTO Serviceanfrage Priorität hoch 2 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="31">
|
||||
<name>TTO Serviceanfrage Priorität hoch 4 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="32">
|
||||
<name>TTO Serviceanfrage Priorität hoch 8 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="37">
|
||||
<name>TTO Serviceanfrage Priorität niedrig 16 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="38">
|
||||
<name>TTO Serviceanfrage Priorität niedrig 32 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="36">
|
||||
<name>TTO Serviceanfrage Priorität niedrig 8 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="35">
|
||||
<name>TTO Serviceanfrage Priorität mittel 16 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="33">
|
||||
<name>TTO Serviceanfrage Priorität mittel 4 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="34">
|
||||
<name>TTO Serviceanfrage Priorität mittel 8 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="15">
|
||||
<name>TTR Vorfall Priorität kritisch 1 Stunde</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="16">
|
||||
<name>TTR Vorfall Priorität kritisch 2 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="17">
|
||||
<name>TTR Vorfall Priorität kritisch 4 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="18">
|
||||
<name>TTR Vorfall Priorität hoch 2 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="19">
|
||||
<name>TTR Vorfall Priorität hoch 4 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="20">
|
||||
<name>TTR Vorfall Priorität hoch 8 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="25">
|
||||
<name>TTR Vorfall Priorität niedrig 16 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="26">
|
||||
<name>TTR Vorfall Priorität niedrig 32 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="24">
|
||||
<name>TTR Vorfall Priorität niedrig 8 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="23">
|
||||
<name>TTR Vorfall Priorität mittel 16 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="21">
|
||||
<name>TTR Vorfall Priorität mittel 4 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="22">
|
||||
<name>TTR Vorfall Priorität mittel 8 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="41">
|
||||
<name>TTR Serviceanfrage Priorität kritisch 16 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="39">
|
||||
<name>TTR Serviceanfrage Priorität kritisch 4 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="40">
|
||||
<name>TTR Serviceanfrage Priorität kritisch 8 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="43">
|
||||
<name>TTR Serviceanfrage Priorität hoch 16 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="44">
|
||||
<name>TTR Serviceanfrage Priorität hoch 32 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="42">
|
||||
<name>TTR Serviceanfrage Priorität hoch 8 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="50">
|
||||
<name>TTR Serviceanfrage Priorität niedrig 128 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>128</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="48">
|
||||
<name>TTR Serviceanfrage Priorität niedrig 32 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="49">
|
||||
<name>TTR Serviceanfrage Priorität niedrig 64 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>64</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="45">
|
||||
<name>TTR Serviceanfrage Priorität mittel 16 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="46">
|
||||
<name>TTR Serviceanfrage Priorität mittel 32 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="47">
|
||||
<name>TTR Serviceanfrage Priorität mittel 64 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>64</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
</Set>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ContractType alias="ContractType" id="78">
|
||||
<name>Hosting</name>
|
||||
</ContractType>
|
||||
<ContractType alias="ContractType" id="79">
|
||||
<name>IT-Outsourcing</name>
|
||||
</ContractType>
|
||||
<ContractType alias="ContractType" id="77">
|
||||
<name>Wartung</name>
|
||||
</ContractType>
|
||||
<ContractType alias="ContractType" id="76">
|
||||
<name>Support</name>
|
||||
</ContractType>
|
||||
</Set>
|
||||
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<CustomerContract alias="CustomerContract" id="3">
|
||||
<name>Kundenvertrag</name>
|
||||
<org_id>7</org_id>
|
||||
<description>Kundenvertrag zur Bereitstellung von Services fuer einen externen Kunden.</description>
|
||||
<start_date>2026-01-01</start_date>
|
||||
<end_date>2030-12-31</end_date>
|
||||
<cost>10000</cost>
|
||||
<cost_currency>euros</cost_currency>
|
||||
<contracttype_id>79</contracttype_id>
|
||||
<billing_frequency>yearly</billing_frequency>
|
||||
<provider_id>2</provider_id>
|
||||
<status>production</status>
|
||||
</CustomerContract>
|
||||
<CustomerContract alias="CustomerContract" id="1">
|
||||
<name>Kundenvertrag Vertriebsabteilung</name>
|
||||
<org_id>6</org_id>
|
||||
<description>Interner Vertrag zur Bereitstellung von Services fuer die Vertriebsabteilung</description>
|
||||
<start_date>2019-01-01</start_date>
|
||||
<end_date>2030-12-31</end_date>
|
||||
<cost>0</cost>
|
||||
<cost_currency>euros</cost_currency>
|
||||
<contracttype_id>0</contracttype_id>
|
||||
<billing_frequency>monthly</billing_frequency>
|
||||
<provider_id>2</provider_id>
|
||||
<status>production</status>
|
||||
</CustomerContract>
|
||||
</Set>
|
||||
@@ -0,0 +1,219 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="28">
|
||||
<name>Zugriffsprobleme</name>
|
||||
<description>Hilfe bei einem Zugriffsproblem anfordern</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="17">
|
||||
<name>API-Integration</name>
|
||||
<description>Verbindung zwischen internen und externen Anwendungen.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="13">
|
||||
<name>CRM (z. B. Salesforce, HubSpot)</name>
|
||||
<description>Einrichtung, Anpassung und Support für das Customer-Relationship-Management.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="22">
|
||||
<name>Sensibilisierung für Cybersicherheit</name>
|
||||
<description>Schulung der Mitarbeitenden zu bewährten Praktiken (Phishing, Passwörter usw.).</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="3">
|
||||
<name>Datensicherung</name>
|
||||
<description>Automatische Sicherung kritischer Dateien (täglich/wöchentlich/monatlich).</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="21">
|
||||
<name>Datenschutz (DSGVO)</name>
|
||||
<description>Unterstützung bei der Einhaltung gesetzlicher Vorgaben (DSGVO, HIPAA usw.).</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="1">
|
||||
<name>ERP (z. B. SAP, Odoo)</name>
|
||||
<description>Zugriff, Support und Schulung für integrierte Managementsoftware.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="10">
|
||||
<name>Dateispeicherung und -freigabe</name>
|
||||
<description>Bereitstellung kollaborativer Speicherbereiche (z. B. SharePoint, Nextcloud).</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="12">
|
||||
<name>Hardwarevorfall</name>
|
||||
<description>Unterstützung bei einem Hardwareausfall anfordern.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="19">
|
||||
<name>Hardware-Upgrade</name>
|
||||
<description>Austausch oder Erweiterung von Komponenten (RAM, Festplatte usw.).</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="7">
|
||||
<name>Lokales Netzwerk (LAN/Wi-Fi)</name>
|
||||
<description>Installation, Konfiguration und Wartung von Netzwerkgeräten.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="27">
|
||||
<name>Multi-Faktor-Authentifizierung (MFA)</name>
|
||||
<description>Konfiguration und Support für Multi-Faktor-Authentifizierung.</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="4">
|
||||
<name>Fehlerbehebung im Netzwerk</name>
|
||||
<description>Hilfe bei der Behebung eines Netzwerkproblems anfordern.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="5">
|
||||
<name>Bestellung neuer Desktop-Computer</name>
|
||||
<description>Einen neuen Desktop-Computer für neue Mitarbeitende oder als Ersatz für ein altes System bestellen.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="8">
|
||||
<name>Bestellung neuer Laptops</name>
|
||||
<description>Einen neuen Laptop für mobile Mitarbeitende oder als Ersatz für ein altes Gerät bestellen.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="11">
|
||||
<name>Neues Peripheriegerät</name>
|
||||
<description>Ein Peripheriegerät bestellen: Tastatur, Maus, persönlicher Drucker ...</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="20">
|
||||
<name>Sicherheitsaudit</name>
|
||||
<description>Schwachstellenanalysen, Penetrationstests und Empfehlungen.</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="23">
|
||||
<name>Sicherheitsvorfall</name>
|
||||
<description>Reaktion auf Cyberangriffe, Datenlecks oder Sicherheitsverletzungen.</description>
|
||||
<service_id>6</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="6">
|
||||
<name>Serververwaltung</name>
|
||||
<description>Präventive Wartung, Software-Updates und 24/7-Überwachung.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="16">
|
||||
<name>Softwarevorfall</name>
|
||||
<description>Hilfe bei der Behebung eines Softwareproblems anfordern.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="15">
|
||||
<name>Softwarevorfall</name>
|
||||
<description>Unterstützung bei einem softwarebezogenen Problem anfordern.</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>incident</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="18">
|
||||
<name>Softwareinstallation</name>
|
||||
<description>Bereitstellung von Office-Software (z. B. Microsoft 365, LibreOffice) und Geschäftssoftware.</description>
|
||||
<service_id>1</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="14">
|
||||
<name>Individuelle Entwicklung</name>
|
||||
<description>Entwicklung maßgeschneiderter Tools (Dashboards, Automatisierungen, Skripte).</description>
|
||||
<service_id>2</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="24">
|
||||
<name>Benutzerkonto-Erstellung</name>
|
||||
<description>Erstellung von Konten für neue Mitarbeitende oder Auftragnehmer.</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="26">
|
||||
<name>Benutzerkonto-Löschung</name>
|
||||
<description>Deaktivierung von Konten für ausscheidende Mitarbeitende oder am Ende ihrer Verträge.</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="25">
|
||||
<name>Benutzerkonto-Aktualisierung</name>
|
||||
<description>Hinzufügen oder Entfernen von Berechtigungen (z. B. Zugriff auf einen freigegebenen Ordner oder eine Anwendung).</description>
|
||||
<service_id>7</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
<ServiceSubcategory alias="ServiceSubcategory" id="2">
|
||||
<name>VPN-Zugriff</name>
|
||||
<description>Konfiguration und Support für sicheren Fernzugriff auf interne Ressourcen.</description>
|
||||
<service_id>3</service_id>
|
||||
<request_type>service_request</request_type>
|
||||
<status>production</status>
|
||||
<approvalrule_id>0</approvalrule_id>
|
||||
</ServiceSubcategory>
|
||||
</Set>
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ServiceFamily alias="ServiceFamily" id="1">
|
||||
<name>IT-Services</name>
|
||||
<icon>
|
||||
<mimetype>image/svg+xml</mimetype>
|
||||
<filename>icons8-open-end-wrench.svg</filename>
|
||||
<data>PD94bWwgdmVyc2lvbj0iMS4wIj8+CjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2aWV3Qm94PSIwIDAgNDggNDgiIHdpZHRoPSIyNDBweCIgaGVpZ2h0PSIyNDBweCI+PHJhZGlhbEdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2phIiBjeD0iOS4xNjkiIGN5PSIzOC42NyIgcj0iMTIuMTM1IiBncmFkaWVudFVuaXRzPSJ1c2VyU3BhY2VPblVzZSI+PHN0b3Agb2Zmc2V0PSIuNzA2IiBzdG9wLWNvbG9yPSIjNzg3Zjg1Ii8+PHN0b3Agb2Zmc2V0PSIuNzEzIiBzdG9wLWNvbG9yPSIjN2E4MTg3Ii8+PHN0b3Agb2Zmc2V0PSIuNzkzIiBzdG9wLWNvbG9yPSIjOTA5ODlmIi8+PHN0b3Agb2Zmc2V0PSIuODY4IiBzdG9wLWNvbG9yPSIjOWRhNWFlIi8+PHN0b3Agb2Zmc2V0PSIuOTMiIHN0b3AtY29sb3I9IiNhMWFhYjMiLz48L3JhZGlhbEdyYWRpZW50PjxwYXRoIGZpbGw9InVybCgjMEJESnMzV3RwcE1nbzRZOUE3R2dqYSkiIGQ9Ik0xOS45MTUsMjEuOGMtNC42NzksNC42NzktOS4zNzUsOS4zNzUtOS41NTEsOS41NTFsNi4zNjQsNi4zNjQgYzAuMTc3LTAuMTc3LDQuODcyLTQuODcyLDkuNTUxLTkuNTUxTDE5LjkxNSwyMS44eiIvPjxyYWRpYWxHcmFkaWVudCBpZD0iMEJESnMzV3RwcE1nbzRZOUE3R2dqYiIgY3g9IjEzLjQyNSIgY3k9IjM1LjQ5OSIgcj0iMTQuNjg4IiBncmFkaWVudFRyYW5zZm9ybT0icm90YXRlKDE4MCAyNC4zMjIgMjMuNzU4KSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iLjcwNiIgc3RvcC1jb2xvcj0iIzc4N2Y4NSIvPjxzdG9wIG9mZnNldD0iLjcxMyIgc3RvcC1jb2xvcj0iIzdhODE4NyIvPjxzdG9wIG9mZnNldD0iLjc5MyIgc3RvcC1jb2xvcj0iIzkwOTg5ZiIvPjxzdG9wIG9mZnNldD0iLjg2OCIgc3RvcC1jb2xvcj0iIzlkYTVhZSIvPjxzdG9wIG9mZnNldD0iLjkzIiBzdG9wLWNvbG9yPSIjYTFhYWIzIi8+PC9yYWRpYWxHcmFkaWVudD48cGF0aCBmaWxsPSJ1cmwoIzBCREpzM1d0cHBNZ280WTlBN0dnamIpIiBkPSJNMjQuNzI4LDI5LjcxNWM0LjY3OS00LjY3OSw5LjM3NS05LjM3NSw5LjU1MS05LjU1MUwyNy45MTUsMTMuOCBjLTAuMTc3LDAuMTc3LTQuODcyLDQuODcyLTkuNTUxLDkuNTUxTDI0LjcyOCwyOS43MTV6Ii8+PGxpbmVhckdyYWRpZW50IGlkPSIwQkRKczNXdHBwTWdvNFk5QTdHZ2pjIiB4MT0iMjIuMTE5IiB4Mj0iMzMuOTI2IiB5MT0iLTI1NTIuODgzIiB5Mj0iLTI1NjQuNjkiIGdyYWRpZW50VHJhbnNmb3JtPSJtYXRyaXgoLTEgMCAwIDEgMzkuMDQ2IDI1OTguMDMzKSIgZ3JhZGllbnRVbml0cz0idXNlclNwYWNlT25Vc2UiPjxzdG9wIG9mZnNldD0iMCIgc3RvcC1jb2xvcj0iIzhmOTc5ZSIvPjxzdG9wIG9mZnNldD0iMSIgc3RvcC1jb2xvcj0iI2ExYWFiMyIvPjwvbGluZWFyR3JhZGllbnQ+PHBhdGggZmlsbD0idXJsKCMwQkRKczNXdHBwTWdvNFk5QTdHZ2pkKSIgZD0iTTQwLjY2MiwxMy4zMTJjLTEuNjk1LDEuNjk1LTQuNDQ1LDEuNjk1LTYuMTM5LDBzLTEuNjk1LTQuNDQ1LDAtNi4xMzkgYzAuNDE0LTAuNDE0LDIuMDgxLTIuMDgxLDMuNzgtMy43OGMwLjQwNy0wLjQwNywwLjIyNi0xLjExOS0wLjMzMi0xLjI1NmMtMS4zNzctMC4zMzgtMi44NTgtMC40MDktNC4zOTktMC4xMTkgYy00LjUxOSwwLjg1Mi04LjA0Myw0LjYzMy04LjUxMiw5LjIwN2MtMC42ODQsNi42Nyw0Ljg4MywxMi4yMzYsMTEuNTUzLDExLjU1MWM0LjU3NC0wLjQ3LDguMzU1LTMuOTk0LDkuMjA2LTguNTEzIGMwLjI5LTEuNTQxLDAuMjE5LTMuMDIxLTAuMTE5LTQuMzk4Yy0wLjEzOC0wLjU2LTAuODQ5LTAuNzQxLTEuMjU2LTAuMzMyQzQyLjc0MywxMS4yMzEsNDEuMDc2LDEyLjg5OSw0MC42NjIsMTMuMzEyeiIvPjwvc3ZnPgo=</data>
|
||||
<downloads_count>0</downloads_count>
|
||||
</icon>
|
||||
</ServiceFamily>
|
||||
</Set>
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<SLA alias="SLA" id="4">
|
||||
<name>SLA Bronze</name>
|
||||
<description>Service-Level-Agreement Bronze fuer Services mit niedriger Kritikalitaet</description>
|
||||
<org_id>2</org_id>
|
||||
</SLA>
|
||||
<SLA alias="SLA" id="2">
|
||||
<name>SLA Gold</name>
|
||||
<description>Service-Level-Agreement Gold fuer Services mit hoher Kritikalitaet</description>
|
||||
<org_id>2</org_id>
|
||||
</SLA>
|
||||
<SLA alias="SLA" id="3">
|
||||
<name>SLA Silver</name>
|
||||
<description>Service-Level-Agreement Silver fuer Services mit mittlerer Kritikalitaet</description>
|
||||
<org_id>2</org_id>
|
||||
</SLA>
|
||||
</Set>
|
||||
387
datamodels/2.x/itop-service-mgmt/data/data.sample.slt.de_de.xml
Normal file
387
datamodels/2.x/itop-service-mgmt/data/data.sample.slt.de_de.xml
Normal file
@@ -0,0 +1,387 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<SLT alias="SLT" id="5">
|
||||
<name>TTO Vorfall Priorität kritisch 1 Stunde</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="3">
|
||||
<name>TTO Vorfall Priorität kritisch 15 Minuten</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>15</value>
|
||||
<unit>minutes</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="4">
|
||||
<name>TTO Vorfall Priorität kritisch 30 Minuten</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>30</value>
|
||||
<unit>minutes</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="7">
|
||||
<name>TTO Vorfall Priorität hoch 1 Stunde</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="8">
|
||||
<name>TTO Vorfall Priorität hoch 2 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="6">
|
||||
<name>TTO Vorfall Priorität hoch 30 Minuten</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>30</value>
|
||||
<unit>minutes</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="12">
|
||||
<name>TTO Vorfall Priorität niedrig 2 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="13">
|
||||
<name>TTO Vorfall Priorität niedrig 4 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="14">
|
||||
<name>TTO Vorfall Priorität niedrig 8 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="9">
|
||||
<name>TTO Vorfall Priorität mittel 1 Stunde</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="10">
|
||||
<name>TTO Vorfall Priorität mittel 2 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="11">
|
||||
<name>TTO Vorfall Priorität mittel 4 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="27">
|
||||
<name>TTO Serviceanfrage Priorität kritisch 1 Stunde</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="28">
|
||||
<name>TTO Serviceanfrage Priorität kritisch 2 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="29">
|
||||
<name>TTO Serviceanfrage Priorität kritisch 4 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="30">
|
||||
<name>TTO Serviceanfrage Priorität hoch 2 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="31">
|
||||
<name>TTO Serviceanfrage Priorität hoch 4 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="32">
|
||||
<name>TTO Serviceanfrage Priorität hoch 8 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="37">
|
||||
<name>TTO Serviceanfrage Priorität niedrig 16 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="38">
|
||||
<name>TTO Serviceanfrage Priorität niedrig 32 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="36">
|
||||
<name>TTO Serviceanfrage Priorität niedrig 8 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="35">
|
||||
<name>TTO Serviceanfrage Priorität mittel 16 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="33">
|
||||
<name>TTO Serviceanfrage Priorität mittel 4 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="34">
|
||||
<name>TTO Serviceanfrage Priorität mittel 8 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>tto</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="15">
|
||||
<name>TTR Vorfall Priorität kritisch 1 Stunde</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>1</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="16">
|
||||
<name>TTR Vorfall Priorität kritisch 2 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="17">
|
||||
<name>TTR Vorfall Priorität kritisch 4 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="18">
|
||||
<name>TTR Vorfall Priorität hoch 2 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>2</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="19">
|
||||
<name>TTR Vorfall Priorität hoch 4 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="20">
|
||||
<name>TTR Vorfall Priorität hoch 8 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="25">
|
||||
<name>TTR Vorfall Priorität niedrig 16 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="26">
|
||||
<name>TTR Vorfall Priorität niedrig 32 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="24">
|
||||
<name>TTR Vorfall Priorität niedrig 8 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="23">
|
||||
<name>TTR Vorfall Priorität mittel 16 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="21">
|
||||
<name>TTR Vorfall Priorität mittel 4 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="22">
|
||||
<name>TTR Vorfall Priorität mittel 8 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>incident</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="41">
|
||||
<name>TTR Serviceanfrage Priorität kritisch 16 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="39">
|
||||
<name>TTR Serviceanfrage Priorität kritisch 4 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>4</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="40">
|
||||
<name>TTR Serviceanfrage Priorität kritisch 8 Stunden</name>
|
||||
<priority>1</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="43">
|
||||
<name>TTR Serviceanfrage Priorität hoch 16 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="44">
|
||||
<name>TTR Serviceanfrage Priorität hoch 32 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="42">
|
||||
<name>TTR Serviceanfrage Priorität hoch 8 Stunden</name>
|
||||
<priority>2</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>8</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="50">
|
||||
<name>TTR Serviceanfrage Priorität niedrig 128 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>128</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="48">
|
||||
<name>TTR Serviceanfrage Priorität niedrig 32 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="49">
|
||||
<name>TTR Serviceanfrage Priorität niedrig 64 Stunden</name>
|
||||
<priority>4</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>64</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="45">
|
||||
<name>TTR Serviceanfrage Priorität mittel 16 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>16</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="46">
|
||||
<name>TTR Serviceanfrage Priorität mittel 32 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>32</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
<SLT alias="SLT" id="47">
|
||||
<name>TTR Serviceanfrage Priorität mittel 64 Stunden</name>
|
||||
<priority>3</priority>
|
||||
<request_type>service_request</request_type>
|
||||
<metric>ttr</metric>
|
||||
<value>64</value>
|
||||
<unit>hours</unit>
|
||||
</SLT>
|
||||
</Set>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ContactType alias="ContactType" id="75">
|
||||
<name>Administrator</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="73">
|
||||
<name>Einkaeufer</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="1">
|
||||
<name>Kundenbetreuer</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="2">
|
||||
<name>Helpdesk</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="3">
|
||||
<name>Manager</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="74">
|
||||
<name>Vertrieb</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="4">
|
||||
<name>Supportmitarbeiter</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="5">
|
||||
<name>Support Stufe 1</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="6">
|
||||
<name>Teamleiter</name>
|
||||
</ContactType>
|
||||
</Set>
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<DocumentType alias="DocumentType" id="72">
|
||||
<name>Architektur</name>
|
||||
</DocumentType>
|
||||
<DocumentType alias="DocumentType" id="69">
|
||||
<name>Vertrag</name>
|
||||
</DocumentType>
|
||||
<DocumentType alias="DocumentType" id="71">
|
||||
<name>Verfahren</name>
|
||||
</DocumentType>
|
||||
<DocumentType alias="DocumentType" id="70">
|
||||
<name>Prozess</name>
|
||||
</DocumentType>
|
||||
</Set>
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<ContactType alias="ContactType" id="17">
|
||||
<name>Customer manager</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="12">
|
||||
<name>Helpdesk</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="15">
|
||||
<name>Manager</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="14">
|
||||
<name>Support Agent</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="13">
|
||||
<name>Support level1</name>
|
||||
</ContactType>
|
||||
<ContactType alias="ContactType" id="16">
|
||||
<name>Team leader</name>
|
||||
</ContactType>
|
||||
</Set>
|
||||
@@ -2174,22 +2174,5 @@
|
||||
</profiles>
|
||||
</user_rights>
|
||||
<constants/>
|
||||
<snippets>
|
||||
<snippet id="GestionCssInfo" _delta="define">
|
||||
<placement>module</placement>
|
||||
<module>itop-structure</module>
|
||||
<rank>-1</rank>
|
||||
<content>
|
||||
<![CDATA[
|
||||
class GestionCssInfo implements iBackofficeStyleExtension
|
||||
{
|
||||
public function GetStyle(): string
|
||||
{
|
||||
return '.ibo-field--label>.ibo-has-description::after, .ibo-input-with-label--label.ibo-has-description::after{content:"\1F6C8"; font-weight: 200;} ';
|
||||
}
|
||||
}
|
||||
]]>
|
||||
</content>
|
||||
</snippet>
|
||||
</snippets>
|
||||
<snippets/>
|
||||
</itop_design>
|
||||
|
||||
@@ -32,7 +32,6 @@ SetupWebPage::AddModule(
|
||||
'data/data.sample.persons.xml',
|
||||
'data/data.sample.teams.xml',
|
||||
'data/data.sample.contactteam.xml',
|
||||
'data/data.sample.contacttype.xml',
|
||||
'data/data.sample.auditdomain.xml',
|
||||
'data/data.sample.auditcategory.xml',
|
||||
'data/data.sample.auditcategory-auditdomain.xml',
|
||||
|
||||
@@ -61,6 +61,6 @@ class TicketsInstaller extends ModuleInstallerAPI
|
||||
}
|
||||
}
|
||||
// Load localized structural data: predefined query phrases for notifications
|
||||
static::LoadLocalizedData($oConfiguration, $sPreviousVersion, $sCurrentVersion, '3.0.0', __DIR__."/data/{{language_code}}.data.itop-tickets.xml");
|
||||
static::LoadLocalizedDataOnCrossingVersion($oConfiguration, $sPreviousVersion, $sCurrentVersion, '3.0.0', utils::GetAbsoluteModulePath('itop-tickets')."data/data.itop-tickets.en_us.xml");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -14,7 +14,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -11,23 +11,23 @@
|
||||
*
|
||||
*/
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled' => 'installée',
|
||||
'UI:Layout:ExtensionsDetails:BadgeInstalled+' => 'Cette extension fait partie de l\'installation actuelle.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'va être installé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'va être installée',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'Cette extension sera installée lors de l\'installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'ne peut pas être installée',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'Cette extension ne peut pas être installée car une ou plusieurs dépendances ne sont pas satisfaites.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'pas installé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'Cette extension ne peut pas être installée car une ou plusieurs dépendances ne peuvent pas être satisfaites.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'pas installée',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'Cette extension ne fait pas partie de l\'installation actuelle.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'va être désinstallé',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'va être désinstallée',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled+' => 'Cette extension sera désinstallée lors de l\'installation.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable' => 'non désinstallable',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotUninstallable+' => 'Une fois cette extension installée, elle ne devrait pas être désinstallée.',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'supprimé du disque',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk' => 'supprimée du disque',
|
||||
'UI:Layout:ExtensionsDetails:BadgeMissingFromDisk+' => 'Le dossier local de l\'extension a été supprimé du disque. Cela forcera la désinstallation de cette extension.',
|
||||
'UI:Layout:ExtensionsDetails:MenuAboutTitle' => 'À propos de %1$s',
|
||||
'UI:Layout:ExtensionsDetails:MenuAbout' => 'Plus d\'informations',
|
||||
'UI:Layout:ExtensionsDetails:MenuForce' => 'Forcer la désinstallation',
|
||||
'UI:Layout:ExtensionsDetails:MoreActions' => 'Plus d\'actions',
|
||||
'UI:Layout:ExtensionsDetails:TogglerTooltip' => 'Toggle %1$s~~',
|
||||
'UI:Layout:ExtensionsDetails:TogglerTooltip' => 'Basculer %1$s',
|
||||
]);
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -16,7 +16,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled' => 'to be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeInstalled+' => 'This extension will be installed during the setup.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled' => 'cannot be installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies are not satisfied.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+' => 'This extension cannot be installed because one or more dependencies cannot be fulfilled.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled' => 'not installed~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeNotInstalled+' => 'This extension is not part of the current installation.~~',
|
||||
'UI:Layout:ExtensionsDetails:BadgeToBeUninstalled' => 'to be uninstalled~~',
|
||||
|
||||
@@ -58,11 +58,11 @@ const CombodoCKEditorHandler = {
|
||||
// Adjust size if passed in configuration
|
||||
// - Width
|
||||
if (aConfiguration.width !== undefined) {
|
||||
editor.editing.view.on('change', writer => { writer.setStyle( 'width', aConfiguration.width, editor.editing.view.document.getRoot() ); } );
|
||||
editor.editing.view.change( writer => { writer.setStyle( 'width', aConfiguration.width, editor.editing.view.document.getRoot() ); } );
|
||||
}
|
||||
// - Height
|
||||
if (aConfiguration.height !== undefined) {
|
||||
editor.editing.view.on('change', writer => { writer.setStyle( 'height', aConfiguration.height, editor.editing.view.document.getRoot() ); } );
|
||||
editor.editing.view.change( writer => { writer.setStyle( 'height', aConfiguration.height, editor.editing.view.document.getRoot() ); } );
|
||||
}
|
||||
|
||||
this.instances[sElem] = editor;
|
||||
|
||||
@@ -51,7 +51,7 @@ $sOperation = utils::ReadParam('operation', '');
|
||||
$oP->SetBreadCrumbEntry('ui-tool-universalsearch', Dict::S('Menu:UniversalSearchMenu'), Dict::S('Menu:UniversalSearchMenu+'), '', 'fas fa-search', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
|
||||
//$sSearchHeaderForceDropdown
|
||||
$sSearchHeaderForceDropdown = '<select id="select_class" name="baseClass" onChange="this.form.trigger(\'submit\');">';
|
||||
$sSearchHeaderForceDropdown = '<select id="select_class" name="baseClass" onChange="this.form.submit();">';
|
||||
$aClassLabels = [];
|
||||
foreach (MetaModel::GetClasses('bizmodel, grant_by_profile') as $sCurrentClass) {
|
||||
if ((MetaModel::HasCategory($sCurrentClass, 'grant_by_profile') && UserRights::IsActionAllowed($sCurrentClass, UR_ACTION_BULK_MODIFY))
|
||||
|
||||
@@ -54,7 +54,7 @@ try {
|
||||
|
||||
$oP->SetBreadCrumbEntry('ui-tool-tag-admin', Dict::S('Menu:TagAdminMenu'), Dict::S('Menu:TagAdminMenu+'), '', 'fas fa-tags', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES);
|
||||
|
||||
$sSearchHeaderForceDropdown = '<select id="select_class" name="class" onChange="this.form.trigger(\'submit\');">';
|
||||
$sSearchHeaderForceDropdown = '<select id="select_class" name="class" onChange="this.form.submit();">';
|
||||
$aClassLabels = [];
|
||||
foreach (MetaModel::EnumChildClasses($sBaseClass, ENUM_CHILD_CLASSES_EXCLUDETOP) as $sCurrentClass) {
|
||||
$aClassLabels[$sCurrentClass] = MetaModel::GetName($sCurrentClass);
|
||||
|
||||
@@ -545,7 +545,7 @@ class iTopExtensionsMap
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $bKeepExtensionsHavingMissingDependencies && count($oExtension->aMissingDependencies) > 0) {
|
||||
if (! $bKeepExtensionsHavingMissingDependencies && $oExtension->HasDependencyIssue()) {
|
||||
//skip extensions with dependency issues
|
||||
continue;
|
||||
}
|
||||
@@ -562,19 +562,20 @@ class iTopExtensionsMap
|
||||
public function GetAllExtensionsOptionInfo(bool $bRemoteExtensionsShouldBeMandatory = true): array
|
||||
{
|
||||
$aRes = [];
|
||||
foreach ($this->GetAllExtensionsToDisplayInSetup(false, $bRemoteExtensionsShouldBeMandatory) as $sCode => $oExtension) {
|
||||
foreach ($this->GetAllExtensionsToDisplayInSetup(true, $bRemoteExtensionsShouldBeMandatory) as $sCode => $oExtension) {
|
||||
$aRes[] = [
|
||||
'extension_code' => $oExtension->sCode,
|
||||
'title' => $oExtension->sLabel,
|
||||
'description' => $oExtension->sDescription,
|
||||
'more_info' => $oExtension->sMoreInfoUrl,
|
||||
'default' => true, // by default offer to install all modules
|
||||
'modules' => $oExtension->aModules,
|
||||
'mandatory' => $oExtension->bMandatory,
|
||||
'source_label' => $oExtension->GetExtensionSourceLabel(),
|
||||
'uninstallable' => $oExtension->CanBeUninstalled(),
|
||||
'missing' => $oExtension->bRemovedFromDisk,
|
||||
'version' => $oExtension->sVersion,
|
||||
'extension_code' => $oExtension->sCode,
|
||||
'title' => $oExtension->sLabel,
|
||||
'description' => $oExtension->sDescription,
|
||||
'more_info' => $oExtension->sMoreInfoUrl,
|
||||
'default' => true, // by default offer to install all modules
|
||||
'modules' => $oExtension->aModules,
|
||||
'mandatory' => $oExtension->bMandatory,
|
||||
'dependency_issue' => $oExtension->HasDependencyIssue(),
|
||||
'source_label' => $oExtension->GetExtensionSourceLabel(),
|
||||
'uninstallable' => $oExtension->CanBeUninstalled(),
|
||||
'missing' => $oExtension->bRemovedFromDisk,
|
||||
'version' => $oExtension->sVersion,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ use DBObjectSet;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use SetupLog;
|
||||
use TagSetFieldData;
|
||||
|
||||
require_once APPROOT.'setup/feature_removal/ModelReflectionSerializer.php';
|
||||
|
||||
@@ -68,6 +69,10 @@ abstract class AbstractSetupAudit
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MetaModel::IsSameFamily($sClass, TagSetFieldData::class)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!MetaModel::IsStandaloneClass($sClass)) {
|
||||
$iCount = $this->Count($sClass);
|
||||
$this->aFinalClassesToCleanup[$sClass] = $iCount;
|
||||
|
||||
@@ -176,7 +176,7 @@ class iTopExtension
|
||||
};
|
||||
}
|
||||
|
||||
public function IsRemote(): string
|
||||
public function IsRemote(): bool
|
||||
{
|
||||
return $this->sSource === self::SOURCE_REMOTE;
|
||||
}
|
||||
@@ -200,4 +200,9 @@ class iTopExtension
|
||||
{
|
||||
return $this->sLabel !== '';
|
||||
}
|
||||
|
||||
public function HasDependencyIssue(): bool
|
||||
{
|
||||
return count($this->aMissingDependencies) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3688,6 +3688,32 @@ to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/form</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -3818,6 +3844,58 @@ to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/options-resolver</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/password-hasher</product>
|
||||
<author>Robin Chalas - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -3870,6 +3948,32 @@ to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/polyfill-intl-icu</product>
|
||||
<author>Nicolas Grekas - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -3974,6 +4078,58 @@ to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/property-access</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/property-info</product>
|
||||
<author>Kévin Dunglas - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2015-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -4026,6 +4182,58 @@ to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/security-core</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/security-csrf</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -4182,6 +4390,32 @@ to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
<product scope="lib">symfony/validator</product>
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Copyright (c) 2004-present Fabien Potencier
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is furnished
|
||||
to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
@@ -4248,32 +4482,12 @@ THE SOFTWARE.
|
||||
<author>Fabien Potencier - Symfony Community</author>
|
||||
<license_type>MIT</license_type>
|
||||
<text><![CDATA[
|
||||
Icons are from "Tabler Icons" (https://github.com/tabler/tabler-icons), a set of
|
||||
free MIT-licensed high-quality SVG icons.
|
||||
JetBrains Mono typeface (https://www.jetbrains.com/lp/mono/) is available
|
||||
under the SIL Open Font License 1.1 and can be used free of charge, for both
|
||||
commercial and non-commercial purposes. You do not need to give credit to
|
||||
JetBrains, although we will appreciate it very much if you do.
|
||||
|
||||
-----
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2020-2022 Paweł Kuna
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
Licence: https://github.com/JetBrains/JetBrainsMono/blob/master/OFL.txt
|
||||
]]></text>
|
||||
</license>
|
||||
<license>
|
||||
@@ -4316,7 +4530,7 @@ THE SOFTWARE.
|
||||
published by the Free Software Foundation, either version 3 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
2002-2025 Nicola Asuni - Tecnick.com LTD
|
||||
2002-2026 Nicola Asuni - Tecnick.com LTD
|
||||
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
@@ -4324,7 +4538,7 @@ THE SOFTWARE.
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://www.fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -4493,7 +4707,7 @@ Library.
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 3, 29 June 2007
|
||||
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
|
||||
Copyright (C) 2007 Free Software Foundation, Inc. <https://www.fsf.org/>
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
@@ -5137,7 +5351,7 @@ the "copyright" line and a pointer to where the full notice is found.
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
@@ -5156,14 +5370,14 @@ might be different; for a GUI interface, you would use an "about box".
|
||||
You should also get your employer (if you work as a programmer) or school,
|
||||
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||
For more information on this, and how to apply and follow the GNU GPL, see
|
||||
<http://www.gnu.org/licenses/>.
|
||||
<https://www.gnu.org/licenses/>.
|
||||
|
||||
The GNU General Public License does not permit incorporating your program
|
||||
into proprietary programs. If your program is a subroutine library, you
|
||||
may consider it more useful to permit linking proprietary applications with
|
||||
the library. If this is what you want to do, use the GNU Lesser General
|
||||
Public License instead of this License. But first, please read
|
||||
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
<https://www.gnu.org/philosophy/why-not-lgpl.html>.
|
||||
|
||||
**********************************************************************
|
||||
**********************************************************************
|
||||
|
||||
@@ -310,85 +310,47 @@ abstract class ModuleInstallerAPI
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to load localized data in iTop not only at the module installation but also if during an upgrade you pass over the version which brought those data
|
||||
*
|
||||
* @param \Config $oConfiguration
|
||||
* @param string $sPreviousVersion The previous version of the module (empty string will force the loading)
|
||||
* @param string $sCurrentVersion The current version of the module
|
||||
* @param string $sFirstLoadingVersion The first module version for which the data loading should be performed (e.g. '3.0.0')
|
||||
* @param string $sFilePattern The pattern of the file to load, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
|
||||
* Expected values for the three version parameters: Valid examples: '3.2', '3.2.0', '3.2-beta1'. Invalid examples: '3', '3.2.', '3.2-beta-1', '3.2 beta1'.
|
||||
* @param string $sPreviousVersion The previous version of the module (empty string in case of first install)
|
||||
* @param string $sCurrentVersion The current version of the module. Cannot be empty.
|
||||
* @param string $sFirstLoadingVersion If your upgrade passes over the FirstLoadingVersion or in case of fresh install, the localized data will be loaded. This is useful when you want to load (structural) data on a module upgrade. Cannot be empty.
|
||||
* @param string $sDefaultFileName The file to load (If localization is expected then provided file name must end by '.en_us.xml')
|
||||
* If the default iTop language is french and a localized variant of the $sDefaultFileName ending by '.fr_fr.xml' exists, then that file with french data will be loaded.
|
||||
*
|
||||
* @return void
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
*/
|
||||
public static function LoadLocalizedData(Config $oConfiguration, string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
|
||||
public static function LoadLocalizedDataOnCrossingVersion(Config $oConfiguration, string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sDefaultFileName): void
|
||||
{
|
||||
self::AssertLoadLocalizedDataParametersAreValid($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sFilePattern);
|
||||
|
||||
// It's not very clear if it makes sense to test a particular version,
|
||||
// as the loading mechanism checks object existence using reconc_keys
|
||||
// and do not recreate them, nor update existing.
|
||||
// Without test, new entries added to the data files, would be automatically loaded
|
||||
if (($sPreviousVersion === '') ||
|
||||
(version_compare($sPreviousVersion, $sCurrentVersion, '<')
|
||||
&& version_compare($sPreviousVersion, $sFirstLoadingVersion, '<'))) {
|
||||
|
||||
// Note: There is an issue when upgrading, default language cannot be retrieved from the passed configuration, we have to read it from the disk
|
||||
self::AssertLoadLocalizedDataOnCrossingVersionParametersAreValid($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion);
|
||||
if (self::IsVersionCrossed($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion)) {
|
||||
// Note: on upgrade, the default language cannot be retrieved from the passed configuration, it must be read from disk (see StructureInstaller::AfterDatabaseCreation)
|
||||
if (utils::IsNullOrEmptyString($sPreviousVersion)) {
|
||||
// Fresh install
|
||||
$sDefaultLanguage = $oConfiguration->GetDefaultLanguage();
|
||||
$sWishedLanguage = $oConfiguration->GetDefaultLanguage();
|
||||
} else {
|
||||
// Upgrade
|
||||
$sDefaultLanguage = utils::GetConfig(true)->GetDefaultLanguage();
|
||||
}
|
||||
|
||||
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sFilePattern);
|
||||
if ($sFileName !== '') {
|
||||
self::XMLFileLoad($sFileName);
|
||||
$sWishedLanguage = utils::GetConfig(true)->GetDefaultLanguage();
|
||||
}
|
||||
self::LoadLocalizedData($sWishedLanguage, $sDefaultFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \CoreUnexpectedValue
|
||||
*/
|
||||
private static function AssertLoadLocalizedDataParametersAreValid(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sFilePattern): void
|
||||
{
|
||||
if (($sPreviousVersion !== '') && !self::IsValidLocalizedDataVersion($sPreviousVersion)) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedData expects sPreviousVersion to be empty or match x.y[.z][-name], got '{$sPreviousVersion}'");
|
||||
}
|
||||
|
||||
if (!self::IsValidLocalizedDataVersion($sCurrentVersion)) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedData expects sCurrentVersion to match x.y[.z][-name], got '{$sCurrentVersion}'");
|
||||
}
|
||||
|
||||
if (!self::IsValidLocalizedDataVersion($sFirstLoadingVersion)) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedData expects sFirstLoadingVersion to match x.y[.z][-name], got '{$sFirstLoadingVersion}'");
|
||||
}
|
||||
|
||||
if (utils::IsNullOrEmptyString($sFilePattern)) {
|
||||
throw new CoreUnexpectedValue('LoadLocalizedData expects sFilePattern to be a non-empty string');
|
||||
}
|
||||
|
||||
if (substr_count($sFilePattern, '{{language_code}}') !== 1) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedData expects sFilePattern to contain the exact placeholder '{{language_code}}' exactly once");
|
||||
}
|
||||
}
|
||||
|
||||
private static function IsValidLocalizedDataVersion(string $sVersion): bool
|
||||
{
|
||||
return (preg_match('/^\d+\.\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)?$/', $sVersion) === 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array|string $sFileName
|
||||
* @param \XMLDataLoader $oDataLoader
|
||||
* Helper to load a localized data file based on the default language of the application.
|
||||
* @param string $sDefaultLanguage The default language of the application, used to build the localized file name
|
||||
* @param string $sDefaultFile The default file to load, must be ending with .en_us.xml to be localized
|
||||
*
|
||||
* @return void
|
||||
* @throws \Exception
|
||||
*/
|
||||
public static function XMLFileLoad(string $sFileName): void
|
||||
public static function LoadLocalizedData(string $sDefaultLanguage, string $sDefaultFile): void
|
||||
{
|
||||
|
||||
$sFileName = self::GetLocalizedFileName($sDefaultLanguage, $sDefaultFile);
|
||||
if (!file_exists($sFileName)) {
|
||||
throw new Exception("File $sFileName not found");
|
||||
}
|
||||
@@ -402,26 +364,77 @@ abstract class ModuleInstallerAPI
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sLanguage The language code to use for localization (e.g. 'EN US')
|
||||
* @param string $sFilePattern The full path+name of the file to localize, with {{language_code}} as placeholder for the language code (e.g. 'data.sample.{{language_code}}.xml')
|
||||
* Helper to get the localized file name for a given language code, based on the original file name which must end by .en_us.xml
|
||||
* @param string $sLanguage The language code to use for localization (e.g. 'FR FR' or 'fr_fr')
|
||||
* @param string $sOriginalFileName The full path+name of the file to localize. If ending with .en_us.xml, it searches for a localized file.
|
||||
*
|
||||
* @return string The localized file name if found, or an empty string if not found
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
* @return string The localized file name if found otherwise the original file name
|
||||
* @throws \Exception If the original file name ends with .en_us.xml and does not exist
|
||||
*/
|
||||
public static function GetLocalizedFileName($sLanguage, string $sFilePattern): string
|
||||
public static function GetLocalizedFileName(string $sLanguage, string $sOriginalFileName): string
|
||||
{
|
||||
$sLang = str_replace(' ', '_', strtolower($sLanguage));
|
||||
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
|
||||
if (!file_exists($sFileName)) {
|
||||
$sLang = 'en_us';
|
||||
$sFileName = str_replace('{{language_code}}', $sLang, $sFilePattern);
|
||||
}
|
||||
if (file_exists($sFileName)) {
|
||||
return $sFileName;
|
||||
if (str_ends_with($sOriginalFileName, '.en_us.xml')) {
|
||||
// If the original file which can be localized, does not exist, then even if the localized file itself exists, we want to raise this design issue.
|
||||
if (!file_exists($sOriginalFileName)) {
|
||||
throw new Exception("File $sOriginalFileName not found, it must exist when required by the module or as iTop fallback language when no localized file exists for the iTop default language");
|
||||
}
|
||||
// Search for a file for the requested language,
|
||||
$sLang = '.'.str_replace(' ', '_', strtolower($sLanguage)).'.xml';
|
||||
$sFileName = str_replace('.en_us.xml', $sLang, $sOriginalFileName);
|
||||
// localized file not found, fall back to the original file (en_us)
|
||||
if (!file_exists($sFileName)) {
|
||||
SetupLog::Debug("File for iTop default language $sFileName not found, fall back to file $sOriginalFileName");
|
||||
$sFileName = $sOriginalFileName;
|
||||
}
|
||||
} else {
|
||||
SetupLog::Warning("No data file matching the pattern $sFilePattern and language_code $sLang was found.");
|
||||
return '';
|
||||
// If the original file is not localizable, then we just return it as is
|
||||
$sFileName = $sOriginalFileName;
|
||||
}
|
||||
return $sFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \CoreUnexpectedValue
|
||||
*/
|
||||
private static function AssertLoadLocalizedDataOnCrossingVersionParametersAreValid(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion): void
|
||||
{
|
||||
if (($sPreviousVersion !== '') && !self::IsValidVersionFormat($sPreviousVersion)) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedDataOnCrossingVersion expects sPreviousVersion to be empty or match x.y[.z][-name], got '{$sPreviousVersion}'");
|
||||
}
|
||||
if (!self::IsValidVersionFormat($sCurrentVersion)) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedDataOnCrossingVersion expects sCurrentVersion to match x.y[.z][-name], got '{$sCurrentVersion}'");
|
||||
}
|
||||
if (utils::IsNullOrEmptyString($sFirstLoadingVersion) || !self::IsValidVersionFormat($sFirstLoadingVersion)) {
|
||||
throw new CoreUnexpectedValue("LoadLocalizedDataOnCrossingVersion expects sFirstLoadingVersion to match x.y[.z][-name], got '{$sFirstLoadingVersion}'");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a module version matches x.y[.z][-name].
|
||||
* Valid examples: '3.2', '3.2.1', '3.2.3-2', '3.3.0-dev', '10.14-beta2'.
|
||||
* Invalid examples: '3', 'v3.2', '3.2.1.4', '3.2-rc.1', '3.2 beta1'.
|
||||
*
|
||||
* @param string $sVersion
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function IsValidVersionFormat(string $sVersion): bool
|
||||
{
|
||||
return (preg_match('/^\d+\.\d+(?:\.\d+)?(?:-[A-Za-z0-9]+)?$/', $sVersion) === 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sPreviousVersion
|
||||
* @param string $sCurrentVersion
|
||||
* @param string $sFirstLoadingVersion
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function IsVersionCrossed(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion): bool
|
||||
{
|
||||
return ($sPreviousVersion === '') ||
|
||||
(version_compare($sPreviousVersion, $sCurrentVersion, '<')
|
||||
&& version_compare($sPreviousVersion, $sFirstLoadingVersion, '<')
|
||||
&& version_compare($sFirstLoadingVersion, $sCurrentVersion, '<='));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -933,6 +933,8 @@ class RunTimeEnvironment
|
||||
@chmod($sFinalConfig, 0440); // Read-only for owner and group, nothing for others
|
||||
|
||||
SetupUtils::rrmdir(dirname($sBuildConfig)); // Cleanup the temporary build dir if empty
|
||||
MetaModel::ResetAllCaches($this->sBuildEnv);
|
||||
MetaModel::ResetAllCaches($this->sFinalEnv);
|
||||
|
||||
if (! isset($_SESSION)) {
|
||||
//used in all UI setups (not unattended)
|
||||
@@ -1101,7 +1103,7 @@ class RunTimeEnvironment
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$oConfig->Set('access_mode', ACCESS_FULL);
|
||||
|
||||
$sDefaultLanguage = $oConfig->GetDefaultLanguage();
|
||||
$oDataLoader = new XMLDataLoader();
|
||||
|
||||
CMDBObject::SetCurrentChangeFromParams("Initialization from XML files for the selected modules ");
|
||||
@@ -1147,7 +1149,7 @@ class RunTimeEnvironment
|
||||
// in the current database
|
||||
foreach ($aPreviouslyLoadedFiles as $sFileRelativePath) {
|
||||
$sFileName = APPROOT.$sFileRelativePath;
|
||||
SetupLog::Info("Loading file: $sFileName (just to get the keys mapping)");
|
||||
SetupLog::Info("Loading file: $sFileName (just to build & cache the keys mapping)");
|
||||
if (!file_exists($sFileName)) {
|
||||
throw(new Exception("File $sFileName does not exist"));
|
||||
}
|
||||
@@ -1163,7 +1165,7 @@ class RunTimeEnvironment
|
||||
if (!file_exists($sFileName)) {
|
||||
throw(new Exception("File $sFileName does not exist"));
|
||||
}
|
||||
|
||||
$sFileName = ModuleInstallerAPI::GetLocalizedFileName($sDefaultLanguage, $sFileName);
|
||||
$oDataLoader->LoadFile($sFileName);
|
||||
$sResult = sprintf("loading of %s done.", basename($sFileName));
|
||||
SetupLog::Info($sResult);
|
||||
|
||||
@@ -553,15 +553,14 @@ class SetupUtils
|
||||
*
|
||||
* @since 3.0.0 N°2214 replace SetupLog::Log calls by CheckResult::TRACE
|
||||
*/
|
||||
public static function CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules)
|
||||
public static function CheckSelectedModules(array $aRelDirsToScan, $aSelectedModules)
|
||||
{
|
||||
$aResult = [];
|
||||
|
||||
$aDirsToScan = [APPROOT.$sSourceDir];
|
||||
$sExtensionsPath = APPROOT.$sExtensionDir;
|
||||
if (is_dir($sExtensionsPath)) {
|
||||
// if the extensions dir exists, scan it for additional modules as well
|
||||
$aDirsToScan[] = $sExtensionsPath;
|
||||
$aDirsToScan = [];
|
||||
foreach ($aRelDirsToScan as $sRelDir) {
|
||||
if (is_dir(APPROOT.$sRelDir)) {
|
||||
$aDirsToScan[] = APPROOT.$sRelDir;
|
||||
}
|
||||
}
|
||||
require_once(APPROOT.'setup/modulediscovery.class.inc.php');
|
||||
try {
|
||||
@@ -1662,11 +1661,14 @@ JS
|
||||
|
||||
$aAvailableModules = $oProductionEnv->AnalyzeInstallation($oConfig, $aDirsToScan, $bAbortOnMissingDependency, $aModulesToLoad);
|
||||
|
||||
foreach ($aAvailableModules as $key => $aModule) {
|
||||
$bIsExtra = (array_key_exists('root_dir', $aModule) && (strpos($aModule['root_dir'], $sExtraDir) !== false)); // Some modules (root, datamodel) have no 'root_dir'
|
||||
if ($bIsExtra) {
|
||||
// Modules in data/production-modules/ are considered as mandatory and always installed
|
||||
$aAvailableModules[$key]['visible'] = false;
|
||||
$bRemoteExtensionsShouldBeMandatory = !$oWizard->GetParameter('force-uninstall', false);
|
||||
if ($bRemoteExtensionsShouldBeMandatory) {
|
||||
foreach ($aAvailableModules as $key => $aModule) {
|
||||
$bIsExtra = (array_key_exists('root_dir', $aModule) && (strpos($aModule['root_dir'], $sExtraDir) !== false)); // Some modules (root, datamodel) have no 'root_dir'
|
||||
if ($bIsExtra) {
|
||||
// Modules in data/production-modules/ are considered as mandatory and always installed
|
||||
$aAvailableModules[$key]['visible'] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ class InstallationFileService
|
||||
continue;
|
||||
}
|
||||
if ($this->CanChooseUnpackageExtension($oExtension)) {
|
||||
if (($oExtension->bVisible) && (count($oExtension->aMissingDependencies) === 0)) {
|
||||
if ($oExtension->bVisible && !$oExtension->HasDependencyIssue()) {
|
||||
$aCurrentModules = [];
|
||||
$aUnselectableModules = [];
|
||||
$bIsExtensionSelectable = true;
|
||||
|
||||
@@ -244,7 +244,8 @@ $aChecks = SetupUtils::CheckBackupPrerequisites(APPROOT.'data'); // mmm should b
|
||||
$aSelectedModules = $oParams->Get('selected_modules');
|
||||
$sSourceDir = $oParams->Get('source_dir', 'datamodels/latest');
|
||||
$sExtensionDir = $oParams->Get('extensions_dir', 'extensions');
|
||||
$aChecks = array_merge($aChecks, SetupUtils::CheckSelectedModules($sSourceDir, $sExtensionDir, $aSelectedModules));
|
||||
$aRelDirsToScan = [$sSourceDir, $sExtensionDir, "data/$sTargetEnvironment-modules"];
|
||||
$aChecks = array_merge($aChecks, SetupUtils::CheckSelectedModules($aRelDirsToScan, $aSelectedModules));
|
||||
|
||||
foreach ($aChecks as $oCheckResult) {
|
||||
switch ($oCheckResult->iSeverity) {
|
||||
|
||||
@@ -46,7 +46,7 @@ abstract class AbstractWizStepMiscParams extends WizardStep
|
||||
$oPage->add('<fieldset>');
|
||||
|
||||
$oPage->add('<div id="prefix_option" class="collapsable-options">');
|
||||
$oPage->add('<span data-role="setup-collapsable-options--toggler"><label style="font-weight: normal;">Advanced parameters</label></span>');
|
||||
$oPage->add('<span data-role="setup-collapsable-options--toggler"><a href="#" style="font-weight: normal;color:black;">Advanced parameters</a></span>');
|
||||
$oPage->add('<div class="" style="'.(mb_strlen($sChecked) === 0 ? 'display:none' : '').'">');
|
||||
$oPage->add('<input id="force-uninstall" type="checkbox"'.$sChecked.' name="force-uninstall"><label for="force-uninstall"> Unlock any extension uninstallation</label>');
|
||||
$oPage->add('<div class="message message-warning">This could result in data corruption and application crashes.</div>');
|
||||
|
||||
@@ -112,6 +112,22 @@ JS);
|
||||
return;
|
||||
}
|
||||
|
||||
// When the setup reach this step, it already checked whether extensions were uninstallable (during WizStepModulesChoice or combodo-data-feature-removal). We only need to log what has been done.
|
||||
if ($this->oWizard->GetParameter('force-uninstall', false)) {
|
||||
SetupLog::Warning("User disabled uninstallation checks");
|
||||
}
|
||||
$aExtensionsRemoved = json_decode($this->oWizard->GetParameter('removed_extensions'), true) ?? [];
|
||||
$aExtensionsNotUninstallable = json_decode($this->oWizard->GetParameter('extensions_not_uninstallable'), true) ?? [];
|
||||
$aExtensionsForceUninstalled = [];
|
||||
foreach ($aExtensionsRemoved as $sExtensionCode => $sLabel) {
|
||||
if (in_array($sExtensionCode, $aExtensionsNotUninstallable)) {
|
||||
$aExtensionsForceUninstalled[] = $sExtensionCode;
|
||||
}
|
||||
}
|
||||
if (count($aExtensionsForceUninstalled)) {
|
||||
SetupLog::Warning("Extensions uninstalled forcefully : ".implode(',', $aExtensionsForceUninstalled));
|
||||
}
|
||||
|
||||
$oPage->add_ready_script(<<<JS
|
||||
$("#wiz_form").data("installation_status", "not started");
|
||||
ExecuteStep("");
|
||||
|
||||
@@ -31,8 +31,8 @@ class WizStepLandingBeforeAudit extends WizStepModulesChoice
|
||||
$oWizard->SetParameter('db_tls_enabled', $this->oConfig->Get('db_tls.enabled'));
|
||||
$oWizard->SetParameter('db_tls_ca', $this->oConfig->Get('db_tls.ca') ?? '');
|
||||
$oWizard->SetParameter('display_choices', '');
|
||||
$oWizard->SetParameter('extensions_not_uninstallable', '[]');
|
||||
|
||||
$oWizard->SaveParameter('extensions_not_uninstallable', '[]');
|
||||
$oWizard->SaveParameter('use_symbolic_links', MFCompiler::UseSymbolicLinks());
|
||||
$oWizard->SaveParameter('force-uninstall', false);
|
||||
$oWizard->SaveParameter('skip_wizard', false);
|
||||
|
||||
@@ -587,7 +587,7 @@ EOF
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ((isset($aChoice['mandatory']) && $aChoice['mandatory']) ||
|
||||
if ((isset($aChoice['mandatory']) && $aChoice['mandatory'] && (!isset($aChoice['dependency_issue']) || !$aChoice['dependency_issue'])) ||
|
||||
(isset($aSelectedChoices[$sChoiceId]) && ($aSelectedChoices[$sChoiceId] == $sChoiceId))) {
|
||||
$sDisplayChoices .= '<li>'.$aChoice['title'].'</li>';
|
||||
if (isset($aChoice['modules'])) {
|
||||
@@ -637,7 +637,7 @@ EOF
|
||||
if ($sChoiceName == null) {
|
||||
$sChoiceName = $sChoiceId;
|
||||
}
|
||||
if ((isset($aChoice['mandatory']) && $aChoice['mandatory']) ||
|
||||
if ((isset($aChoice['mandatory']) && $aChoice['mandatory'] && (!isset($aChoice['dependency_issue']) || !$aChoice['dependency_issue'])) ||
|
||||
(isset($aSelectedChoices[$sChoiceName]) && ($aSelectedChoices[$sChoiceName] == $sChoiceId))) {
|
||||
$sDisplayChoices .= '<li>'.$aChoice['title'].'</li>';
|
||||
if ($aSelectedExtensions !== null) {
|
||||
@@ -750,13 +750,17 @@ EOF
|
||||
$bSelected = isset($aSelectedComponents[$sChoiceId]) && ($aSelectedComponents[$sChoiceId] === $sChoiceId);
|
||||
$bMissingFromDisk = isset($aChoice['missing']) && $aChoice['missing'] === true;
|
||||
$bMandatory = (isset($aChoice['mandatory']) && $aChoice['mandatory']);
|
||||
$bInstalled = $bMissingFromDisk || $oITopExtension->bInstalled;
|
||||
$bInstalled = $bMissingFromDisk || $oITopExtension?->bInstalled ?? false;
|
||||
$bDependencyIssue = $oITopExtension?->HasDependencyIssue() ?? false;
|
||||
|
||||
$bChecked = $bSelected;
|
||||
$bDisabled = false;
|
||||
if ($bMissingFromDisk) {
|
||||
$bDisabled = true;
|
||||
$bChecked = false;
|
||||
} elseif ($bDependencyIssue) {
|
||||
$bDisabled = true;
|
||||
$bChecked = false;
|
||||
} elseif ($bMandatory) {
|
||||
$bDisabled = true;
|
||||
$bChecked = true;
|
||||
@@ -787,6 +791,8 @@ EOF
|
||||
|
||||
return [
|
||||
'uninstallable' => $bCanBeUninstalled,
|
||||
'dependency_issue' => $bDependencyIssue,
|
||||
'mandatory' => $bMandatory,
|
||||
'missing' => $bMissingFromDisk,
|
||||
'installed' => $bInstalled,
|
||||
'disabled' => $bDisabled,
|
||||
@@ -805,7 +811,7 @@ EOF
|
||||
$sChoiceId = $sParentId.self::$SEP.$index;
|
||||
$aFlags = $this->ComputeChoiceFlags($aChoice, $sChoiceId, $aSelectedComponents, $bAllDisabled, $bDisableUninstallCheck, $this->bUpgrade);
|
||||
|
||||
if ($aFlags['disabled'] && !$aFlags['checked'] && !$aFlags['uninstallable'] && !$bDisableUninstallCheck) {
|
||||
if ($aFlags['disabled'] && !$aFlags['checked'] && !$bDisableUninstallCheck && (!$aFlags['uninstallable'] || $aFlags['mandatory'])) {
|
||||
$this->bCanMoveForward = false;//Disable "Next"
|
||||
}
|
||||
|
||||
@@ -882,6 +888,9 @@ EOF
|
||||
if (!$aFlags['uninstallable']) {
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--not-uninstallable" class="ibo-badge ibo-block ibo-is-yellow" title="Once this extension has been installed, it should not be uninstalled." >cannot be uninstalled</div>';
|
||||
}
|
||||
if ($aFlags['dependency_issue']) {
|
||||
$sTooltip .= '<div id="badge--'.$sId.'--cannot-be-installed" class="ibo-badge ibo-block ibo-is-orange" title="This extension cannot be installed because one or more dependencies are not satisfied." >cannot be installed</div>';
|
||||
}
|
||||
|
||||
$sMetadata = '';
|
||||
if (isset($aChoice['version']) && isset($aChoice['source_label'])) {
|
||||
@@ -939,10 +948,6 @@ EOF
|
||||
|
||||
public function GetNextButtonLabel()
|
||||
{
|
||||
if (!$this->bCanMoveForward) {
|
||||
return 'Non-uninstallable extension missing';
|
||||
}
|
||||
|
||||
if ($this->GetStepInfo(1 + $this->GetStepIndex()) === null) {
|
||||
return 'Check compatibility';
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ class WizStepSummary extends AbstractWizStepInstall
|
||||
$oPage->add('<div class="closed"><a class="title ibo-setup-summary-title" href="#" aria-label="Extensions to be uninstalled">Extensions to be uninstalled</a>');
|
||||
|
||||
$aExtensionsRemoved = json_decode($this->oWizard->GetParameter('removed_extensions'), true) ?? [];
|
||||
$aExtensionsNotUninstallable = json_decode($this->oWizard->GetParameter('extensions_not_uninstallable')) ?? [];
|
||||
$aExtensionsNotUninstallable = json_decode($this->oWizard->GetParameter('extensions_not_uninstallable'), true) ?? [];
|
||||
if (count($aExtensionsRemoved) > 0) {
|
||||
$sExtensionsRemoved = '<ul>';
|
||||
foreach ($aExtensionsRemoved as $sExtensionCode => $sLabel) {
|
||||
|
||||
@@ -26,10 +26,11 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
$aBadges = [];
|
||||
$bUninstallable = $aExtraFlags['uninstallable'] ?? true;
|
||||
$bMissingFromDisk = $aExtraFlags['missing'] ?? false;
|
||||
$bDependencyIssue = $aExtraFlags['dependency_issue'] ?? false;
|
||||
$bSelected = $aExtraFlags['selected'] ?? true;
|
||||
$bDisabled = $aExtraFlags['disabled'] ?? false;
|
||||
$bRemote = $aExtraFlags['remote'] ?? false;
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, $bMissingFromDisk, $sCode);
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, $bMissingFromDisk, $bDependencyIssue, $sCode);
|
||||
$oBadgeInstalled = BadgeUIBlockFactory::MakeGreen(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeInstalled+'),
|
||||
@@ -47,7 +48,7 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
|
||||
$oExtensionDetails = new ExtensionDetails($sCode, $sLabel, $sDescription, $aMetaData, $aBadges, $sAbout);
|
||||
$oExtensionDetails->GetToggler()->SetIsToggled(true);
|
||||
if ($bMissingFromDisk) {
|
||||
if ($bMissingFromDisk || $bDependencyIssue) {
|
||||
$oExtensionDetails->GetToggler()->SetIsToggled(false);
|
||||
$oExtensionDetails->GetToggler()->SetIsDisabled(true);
|
||||
} elseif ((!$bUninstallable || $bRemote) && !$bDisabled) {
|
||||
@@ -70,10 +71,10 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
{
|
||||
$aBadges = [];
|
||||
$bUninstallable = $aExtraFlags['uninstallable'] ?? true;
|
||||
$bCannotBeInstalled = $aExtraFlags['cannot-be-installed'] ?? false;
|
||||
$bDependencyIssue = $aExtraFlags['dependency_issue'] ?? false;
|
||||
$bSelected = $aExtraFlags['selected'] ?? false;
|
||||
$bDisabled = $aExtraFlags['disabled'] ?? false;
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, false, $sCode);
|
||||
self::AddExtraBadges($aBadges, $bUninstallable, false, $bDependencyIssue, $sCode);
|
||||
$oBadgeInstalled = BadgeUIBlockFactory::MakeGrey(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeNotInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeNotInstalled+'),
|
||||
@@ -88,19 +89,13 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
);
|
||||
$oBadgeToBeUninstalled->AddCSSClass('checked');
|
||||
$aBadges[] = $oBadgeToBeUninstalled;
|
||||
if ($bCannotBeInstalled) {
|
||||
$bSelected = false;
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeOrange(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_CANNOT_BE_INSTALLED)
|
||||
);
|
||||
}
|
||||
$oExtensionDetails = new ExtensionDetails($sCode, $sLabel, $sDescription, $aMetaData, $aBadges, $sAbout);
|
||||
|
||||
if ($bCannotBeInstalled) {
|
||||
if ($bDependencyIssue) {
|
||||
$oExtensionDetails->GetToggler()->SetIsToggled(false);
|
||||
$oExtensionDetails->GetToggler()->SetIsDisabled(true);
|
||||
}
|
||||
|
||||
if ($bSelected) {
|
||||
$oExtensionDetails->GetToggler()->SetIsToggled(true);
|
||||
}
|
||||
@@ -112,7 +107,7 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
return $oExtensionDetails;
|
||||
}
|
||||
|
||||
private static function AddExtraBadges(array &$aBadges, bool $bUninstallable, bool $bMissingFromDisk, string $sCode)
|
||||
private static function AddExtraBadges(array &$aBadges, bool $bUninstallable, bool $bMissingFromDisk, bool $bDependencyIssue, string $sCode)
|
||||
{
|
||||
if (!$bUninstallable) {
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeYellow(
|
||||
@@ -128,6 +123,13 @@ class ExtensionDetailsUIBlockFactory extends AbstractUIBlockFactory
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_MISSING_FROM_DISK)
|
||||
);
|
||||
}
|
||||
if ($bDependencyIssue) {
|
||||
$aBadges[] = BadgeUIBlockFactory::MakeOrange(
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled'),
|
||||
Dict::S('UI:Layout:ExtensionsDetails:BadgeCannotBeInstalled+'),
|
||||
self::GetBadgeId($sCode, self::BADGE_ID_CANNOT_BE_INSTALLED)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
{% include "base/components/input/inputlabel.html.twig" %}
|
||||
{% endif %}
|
||||
<select id="{{ oUIBlock.GetId() }}" name="{{ oUIBlock.GetName() }}"
|
||||
{% if oUIBlock.GetSubmitOnChange() %} onChange="$(this).parents('form:first').trigger('submit');" {% endif %}
|
||||
{% if oUIBlock.GetSubmitOnChange() %} onChange="$(this).parents('form').first().trigger('submit');" {% endif %}
|
||||
{% if oUIBlock.IsMultiple() %} multiple {% endif %}
|
||||
class="{% if oUIBlock.IsHidden() %}ibo-is-hidden{% endif %}{% if oUIBlock.GetAdditionalCSSClassesAsString() %} {{ oUIBlock.GetAdditionalCSSClassesAsString() }}{% endif %}"
|
||||
{% if oUIBlock.GetDataAttributes() %}
|
||||
|
||||
@@ -163,6 +163,58 @@ class DataCleanupServiceTest extends \AbstractCleanup
|
||||
$this->AssertSummaryEquals($aExpected, $aRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* N°9831
|
||||
*
|
||||
* A nullable external key configured as DEL_MANUAL must NOT be treated as an issue: it is simply
|
||||
* reset (set to null), exactly like core DBObject::MakeDeletionPlan does. DEL_MANUAL only blocks
|
||||
* for mandatory keys. This mirrors the real "Hypervisor.farm_id -> Farm" case (nullable + DEL_MANUAL).
|
||||
*
|
||||
* Regression guard for the ordering of the IsNullAllowed()/DEL_MANUAL checks in RecursiveDeletion:
|
||||
* reverting that change would make ExecuteCleanup throw here instead of resetting the object.
|
||||
*/
|
||||
public function testExecuteCleanup_NullableManualShouldResetAndNotThrow()
|
||||
{
|
||||
$this->GivenDFRTreeInDB(<<<EOF
|
||||
DFRToRemoveLeaf_1 <- DFRManualNullable_1
|
||||
EOF);
|
||||
|
||||
$aClasses = [ 'DFRToRemoveLeaf' ];
|
||||
$oService = new DataCleanupService();
|
||||
// Must NOT throw: the nullable external key is reset, not reported as an issue
|
||||
$aRes = $oService->ExecuteCleanup($aClasses);
|
||||
|
||||
$aExpected = [
|
||||
['DFRManualNullable', 1, 0 ],
|
||||
['DFRToRemoveLeaf', 0, 1 ],
|
||||
];
|
||||
$this->AssertSummaryEquals($aExpected, $aRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* N°9831
|
||||
*
|
||||
* Summary counterpart of the test above: a nullable DEL_MANUAL external key is reported as an
|
||||
* update (reset), with an issue count of 0. Reverting the RecursiveDeletion change would report
|
||||
* it as an issue instead.
|
||||
*/
|
||||
public function testGetCleanupSummary_NullableManualShouldBeUpdateNotIssue()
|
||||
{
|
||||
$this->GivenDFRTreeInDB(<<<EOF
|
||||
DFRToRemoveLeaf_1 <- DFRManualNullable_1
|
||||
EOF);
|
||||
|
||||
$aClasses = [ 'DFRToRemoveLeaf' ];
|
||||
$oService = new DataCleanupService();
|
||||
$aRes = $oService->GetCleanupSummary($aClasses);
|
||||
|
||||
$aExpected = [
|
||||
['DFRManualNullable', 1, 0, 0 ],
|
||||
['DFRToRemoveLeaf', 0, 1, 0 ],
|
||||
];
|
||||
$this->AssertSummaryEquals($aExpected, $aRes);
|
||||
}
|
||||
|
||||
private function AssertSummaryEquals(array $expected, $actual, $sMessage = '')
|
||||
{
|
||||
$aExpected = [];
|
||||
|
||||
@@ -9,7 +9,6 @@ namespace Combodo\iTop\Test\UnitTest\Module\DataFeatureRemoval;
|
||||
|
||||
use Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity;
|
||||
use Combodo\iTop\DataFeatureRemoval\Service\StaticDeletionPlan;
|
||||
use MetaModel;
|
||||
|
||||
require_once __DIR__."/AbstractCleanup.php";
|
||||
class StaticDeletionPlanTest extends \AbstractCleanup
|
||||
@@ -150,6 +149,66 @@ EOF);
|
||||
$this->AssertSummaryEquals($aExpected, $aRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* N°9831
|
||||
*
|
||||
* A DEL_MANUAL issue must still be reported when the referencing class (DFRManual) is itself part
|
||||
* of the classes to remove AND is processed AFTER the class it points to (DFRToRemoveLeaf).
|
||||
*
|
||||
* This mirrors the real "VirtualMachine -> VirtualHost" case: the setup audit sorts the removed
|
||||
* classes alphabetically and drops abstract classes, so a referencing class such as VirtualMachine
|
||||
* ends up processed after its concrete targets (Farm/Hypervisor/Cloud). Here DFRToRemove is abstract
|
||||
* and DFRToRemoveLeaf is its concrete child, while DFRManual points to DFRToRemove with a mandatory
|
||||
* DEL_MANUAL external key.
|
||||
*
|
||||
* Regression: the plan entity accumulating the issue used to be overwritten when the referencing
|
||||
* class was processed as a top-level class, silently dropping the issue (no blocking message on the
|
||||
* summary page, then a crash at execution time).
|
||||
*/
|
||||
public function testGetCleanupSummary_IssueKeptWhenReferencingClassListedAfterTarget(): void
|
||||
{
|
||||
$this->GivenDFRObjectsInDB(<<<EOF
|
||||
create DFRToRemoveLeaf (name = DFRToRemoveLeaf_1)
|
||||
create DFRManual (name = DFRManual_1, extkey_id = DFRToRemoveLeaf_1)
|
||||
EOF);
|
||||
|
||||
// Target listed BEFORE the referencing class, as produced by the alphabetically sorted audit
|
||||
$aClasses = ['DFRToRemoveLeaf', 'DFRManual'];
|
||||
$oService = new StaticDeletionPlan();
|
||||
$aRes = $oService->GetCleanupSummary($aClasses);
|
||||
|
||||
$aExpected = [
|
||||
'DFRToRemoveLeaf' => ['iDeleteCount' => 1],
|
||||
'DFRManual' => ['iDeleteCount' => 1, 'iIssueCount' => 1],
|
||||
];
|
||||
$this->AssertSummaryEquals($aExpected, $aRes);
|
||||
}
|
||||
|
||||
/**
|
||||
* N°9831
|
||||
*
|
||||
* Control case: the same issue must also be reported when the referencing class is listed BEFORE
|
||||
* its target (this order already worked, e.g. "Enclosure -> Rack"). Together with the test above,
|
||||
* this locks in that issue detection is independent of the processing order.
|
||||
*/
|
||||
public function testGetCleanupSummary_IssueKeptWhenReferencingClassListedBeforeTarget(): void
|
||||
{
|
||||
$this->GivenDFRObjectsInDB(<<<EOF
|
||||
create DFRToRemoveLeaf (name = DFRToRemoveLeaf_1)
|
||||
create DFRManual (name = DFRManual_1, extkey_id = DFRToRemoveLeaf_1)
|
||||
EOF);
|
||||
|
||||
$aClasses = ['DFRManual', 'DFRToRemoveLeaf'];
|
||||
$oService = new StaticDeletionPlan();
|
||||
$aRes = $oService->GetCleanupSummary($aClasses);
|
||||
|
||||
$aExpected = [
|
||||
'DFRToRemoveLeaf' => ['iDeleteCount' => 1],
|
||||
'DFRManual' => ['iDeleteCount' => 1, 'iIssueCount' => 1],
|
||||
];
|
||||
$this->AssertSummaryEquals($aExpected, $aRes);
|
||||
}
|
||||
|
||||
public function testCircularRefsShouldNotRunInfinitely()
|
||||
{
|
||||
$this->GivenDFRObjectsInDB(<<<EOF
|
||||
|
||||
@@ -319,6 +319,58 @@
|
||||
</presentation>
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
</class>
|
||||
<class id="DFRManualNullable" _created_in="itop-structure" _delta="define">
|
||||
<properties>
|
||||
<category>bizmodel,searchable</category>
|
||||
<abstract>false</abstract>
|
||||
<db_table>dfrmanualnullable</db_table>
|
||||
<naming>
|
||||
<attributes/>
|
||||
</naming>
|
||||
<reconciliation>
|
||||
<attributes/>
|
||||
</reconciliation>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="name" xsi:type="AttributeString">
|
||||
<sql>name</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<validation_pattern/>
|
||||
<dependencies/>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
<field id="extkey_id" xsi:type="AttributeExternalKey">
|
||||
<sql>extkey_id</sql>
|
||||
<filter/>
|
||||
<dependencies/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<target_class>DFRToRemove</target_class>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
<tracking_level>all</tracking_level>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<list>
|
||||
<items/>
|
||||
</list>
|
||||
<search>
|
||||
<items/>
|
||||
</search>
|
||||
<details>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="extkey_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
</presentation>
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
</class>
|
||||
<class id="DFRLeafNotToRemove" _created_in="itop-structure" _delta="define">
|
||||
<properties>
|
||||
<category>bizmodel,searchable</category>
|
||||
@@ -718,6 +770,14 @@
|
||||
<entry id="Class:DFRManual/Attribute:name+" _delta="define"><![CDATA[]]></entry>
|
||||
<entry id="Class:DFRManual/Attribute:extkey_id" _delta="define"><![CDATA[Dfrtoremove id]]></entry>
|
||||
<entry id="Class:DFRManual/Attribute:extkey_id+" _delta="define"><![CDATA[]]></entry>
|
||||
<entry id="Class:DFRManualNullable/Name" _delta="define"><![CDATA[]]></entry>
|
||||
<entry id="Class:DFRManualNullable/ComplementaryName" _delta="define"><![CDATA[]]></entry>
|
||||
<entry id="Class:DFRManualNullable" _delta="define"><![CDATA[DFRManualNullable]]></entry>
|
||||
<entry id="Class:DFRManualNullable+" _delta="define"><![CDATA[]]></entry>
|
||||
<entry id="Class:DFRManualNullable/Attribute:name" _delta="define"><![CDATA[Name]]></entry>
|
||||
<entry id="Class:DFRManualNullable/Attribute:name+" _delta="define"><![CDATA[]]></entry>
|
||||
<entry id="Class:DFRManualNullable/Attribute:extkey_id" _delta="define"><![CDATA[Dfrtoremove id]]></entry>
|
||||
<entry id="Class:DFRManualNullable/Attribute:extkey_id+" _delta="define"><![CDATA[]]></entry>
|
||||
</entries>
|
||||
</dictionary>
|
||||
</dictionaries>
|
||||
|
||||
@@ -285,75 +285,137 @@ SQL
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
|
||||
* @dataProvider LoadLocalizedData_RequiredLanguageProvider
|
||||
*/
|
||||
public function testLoadLocalizedData_LoadsOnFirstInstall(): void
|
||||
public function testLoadLocalizedData_LoadRequiredLanguageOnFirstInstall(string $sRequiredLanguage, array $aExpectedOrganizationNames): void
|
||||
{
|
||||
// Given
|
||||
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_FirstInstall_', 'fr_fr');
|
||||
$this->GivenLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
|
||||
$this->GivenLocalizedDataFile($sTmpDir, "fr_fr", $sOrgName);
|
||||
[$oConfig, $sPattern] = $this->GivenLocalizedDataTestContext($sRequiredLanguage);
|
||||
|
||||
// When no previous version, and current version higher than the first loading version
|
||||
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', '3.3.0', '3.0.0', $sPattern);
|
||||
// Then data loaded
|
||||
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
|
||||
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 1);
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.3.0', '3.0.0', $sPattern);
|
||||
|
||||
// Then the expected localized organizations are loaded
|
||||
$this->AssertOrganizationNamesExist($aExpectedOrganizationNames);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||
*/
|
||||
public function testLoadLocalizedData_DoesNotLoadWhenVersionConditionIsNotMet(): void
|
||||
{
|
||||
// Given
|
||||
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_NoLoad_', 'en_us');
|
||||
$this->GivenLocalizedDataFile($sTmpDir, "en_us", $sOrgName);
|
||||
|
||||
// When a previous version that is lower than the first loading version, but higher or equal to the current version
|
||||
ModuleInstallerAPI::LoadLocalizedData($oConfig, '3.0.0', '3.1.0', '3.0.0', $sPattern);
|
||||
// Then no data loaded
|
||||
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||
*/
|
||||
public function testLoadLocalizedData_FallbacksToEnUsWhenLanguageFileIsMissing(): void
|
||||
{
|
||||
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_Fallback_', 'fr_fr');
|
||||
// Intentionally create ONLY en_us file
|
||||
$this->GivenLocalizedDataFile($sTmpDir, 'en_us', $sOrgName);
|
||||
// When loading localized data in fr_fr, but only en_us file exists
|
||||
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', '3.3.0', '3.0.0', $sPattern);
|
||||
|
||||
$this->AssertOrganizationCountByName($sOrgName, 'fr_fr', 0);
|
||||
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedData
|
||||
* @dataProvider LoadLocalizedData_ValidVersionFormatsProvider
|
||||
*/
|
||||
public function testLoadLocalizedData_AcceptsSupportedVersionFormats(string $sCurrentVersion, string $sFirstLoadingVersion): void
|
||||
{
|
||||
[$oConfig, $sOrgName, $sTmpDir, $sPattern] = $this->GivenLocalizedDataTestContext('XML_Load_ValidVersion_', 'en_us');
|
||||
$this->GivenLocalizedDataFile($sTmpDir, 'en_us', $sOrgName);
|
||||
|
||||
ModuleInstallerAPI::LoadLocalizedData($oConfig, '', $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
|
||||
|
||||
$this->AssertOrganizationCountByName($sOrgName, 'en_us', 1);
|
||||
}
|
||||
|
||||
public function LoadLocalizedData_ValidVersionFormatsProvider(): array
|
||||
public function LoadLocalizedData_RequiredLanguageProvider(): array
|
||||
{
|
||||
return [
|
||||
'Current version with suffix' => ['3.2-dev', '3.0.0'],
|
||||
'Current version x.y.z' => ['1.2.4', '1.0'],
|
||||
'Current version x.y.z-suffix' => ['2.3.3-beta', '2.0.0'],
|
||||
'Current version x.y.z-1' => ['1.2.4-1', '1.0.3-2'],
|
||||
'Required fr_fr and file exists' => [
|
||||
'required language' => 'fr_fr',
|
||||
'expected organization names' => ['Client (Test)', 'Département informatique (Test)'],
|
||||
],
|
||||
'Required en_us and file exists' => [
|
||||
'required language' => 'en_us',
|
||||
'expected organization names' => ['Customer (Test)', 'IT Department (Test)'],
|
||||
],
|
||||
'Required de_de but fallback to en_us' => [
|
||||
'required language' => 'de_de',
|
||||
'expected organization names' => ['Customer (Test)', 'IT Department (Test)'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::IsVersionCrossed
|
||||
* @dataProvider IsVersionCrossedProvider
|
||||
*/
|
||||
public function testIsVersionCrossed_ReturnsExpectedValue(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, bool $bExpected): void
|
||||
{
|
||||
$bIsVersionCrossed = ModuleInstallerAPI::IsVersionCrossed($sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion);
|
||||
|
||||
$this->assertSame($bExpected, $bIsVersionCrossed);
|
||||
}
|
||||
|
||||
public function IsVersionCrossedProvider(): array
|
||||
{
|
||||
return [
|
||||
'First install always crosses' => ['', '3.2.0', '3.0.0', true],
|
||||
'Upgrade crosses first loading version' => ['3.0.0', '3.2.0', '3.1.0', true],
|
||||
'Upgrade but first loading version already passed' => ['3.1.0', '3.2.0', '3.0.0', false],
|
||||
'Reinstall same version does not cross' => ['3.1.0', '3.1.0', '3.0.0', false],
|
||||
'Downgrade does not cross' => ['3.2.0', '3.1.0', '3.0.0', false],
|
||||
'First install with suffixed current version' => ['', '3.2-dev', '3.0.0', true],
|
||||
'Upgrade with suffixed current version crosses' => ['1.0.3-2', '1.2.4-1', '1.1.0', true],
|
||||
'Upgrade with suffixed current version below threshold does not cross' => ['1.0.0', '1.2.0-beta', '1.2.0', false],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
|
||||
*/
|
||||
public function testLoadLocalizedData_LoadsWhenVersionCrossingIsTrue(): void
|
||||
{
|
||||
$this->markTestSkipped('Test skipped because failing in CI. Investigation required, cf Bug N°9787');
|
||||
|
||||
[$oConfig, $sPattern] = $this->GivenLocalizedDataTestContext('FR FR', 'data.sample.organizations.en_us.xml');
|
||||
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '3.0.0', '3.2.0', '3.1.0', $sPattern);
|
||||
|
||||
$this->AssertOrganizationNamesExist(['Client (Test)', 'Département informatique (Test)']);
|
||||
}
|
||||
/**
|
||||
* Test that loading a file twice (because of the version conditions) does not create duplicates (idempotent loading).
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
|
||||
*/
|
||||
public function testLoadLocalizedData_IdempotentLoading(): void
|
||||
{
|
||||
// Given
|
||||
[$oConfig, $sPattern] = $this->GivenLocalizedDataTestContext('en_us', 'data.sample.organizations.en_us.xml');
|
||||
|
||||
// When LoadLocalizedData is called twice with conditions that would load the file both times
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.0.1', '3.0.0', $sPattern);
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '3.0.1', '3.1.0', '3.0.2', $sPattern);
|
||||
|
||||
// Then no duplicated data load side effect and values remain stable
|
||||
foreach (['Customer (Test)', 'IT Department (Test)'] as $sExpectedName) {
|
||||
$oSet = new \DBObjectSet(\DBSearch::FromOQL("SELECT Organization WHERE name = :org_name"), [], ['org_name' => $sExpectedName]);
|
||||
$this->assertSame(1, $oSet->Count(), "Expected exactly one Organization named '{$sExpectedName}' after loading twice (idempotency)");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
|
||||
*/
|
||||
public function testLoadLocalizedData_LoadsRequestedNonEnUsFileWhenItExists(): void
|
||||
{
|
||||
[$oConfig, $sPattern] = $this->GivenLocalizedDataTestContext('en_us', 'data.sample.organizations.fr_fr.xml');
|
||||
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.3.0', '3.0.0', $sPattern);
|
||||
|
||||
$this->AssertOrganizationNamesExist(['Client (Test)', 'Département informatique (Test)']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
|
||||
*/
|
||||
public function testLoadLocalizedData_ThrowsWhenRequestedEnUsFileDoesNotExist(): void
|
||||
{
|
||||
[$oConfig, $sPattern] = $this->GivenLocalizedDataTestContext('en_us', 'data.sample.missing-file.en_us.xml', false);
|
||||
|
||||
$this->expectException(\Exception::class);
|
||||
$this->expectExceptionMessage("File $sPattern not found");
|
||||
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, '', '3.3.0', '3.0.0', $sPattern);
|
||||
}
|
||||
|
||||
/**
|
||||
* @covers \ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion
|
||||
* @dataProvider LoadLocalizedData_InvalidParametersProvider
|
||||
*/
|
||||
public function testLoadLocalizedData_ThrowsOnInvalidParameters(string $sPreviousVersion, string $sCurrentVersion, string $sFirstLoadingVersion, string $sPattern, string $sExpectedMessage): void
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$this->assertNotNull($oConfig);
|
||||
|
||||
$this->expectException(\CoreUnexpectedValue::class);
|
||||
$this->expectExceptionMessage($sExpectedMessage);
|
||||
|
||||
ModuleInstallerAPI::LoadLocalizedDataOnCrossingVersion($oConfig, $sPreviousVersion, $sCurrentVersion, $sFirstLoadingVersion, $sPattern);
|
||||
}
|
||||
|
||||
public function LoadLocalizedData_InvalidParametersProvider(): array
|
||||
{
|
||||
$sTmpDir = static::CreateTmpdir();
|
||||
@@ -364,93 +426,59 @@ SQL
|
||||
'previous' => 'v3.2',
|
||||
'current' => '3.2.0',
|
||||
'first' => '3.0.0',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.en_us.xml',
|
||||
'message' => 'sPreviousVersion',
|
||||
],
|
||||
'Invalid current version format' => [
|
||||
'previous' => '',
|
||||
'current' => '3',
|
||||
'first' => '3.0.0',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.en_us.xml',
|
||||
'message' => 'sCurrentVersion',
|
||||
],
|
||||
'Invalid first loading version format' => [
|
||||
'previous' => '',
|
||||
'current' => '3.2.0',
|
||||
'first' => '3.0.0-beta.1',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.en_us.xml',
|
||||
'message' => 'sFirstLoadingVersion',
|
||||
],
|
||||
'Missing strict placeholder' => [
|
||||
'previous' => '',
|
||||
'current' => '3.2.0',
|
||||
'first' => '3.0.0',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'data.{{LANGUAGE_CODE}}.xml',
|
||||
'message' => "{{language_code}}",
|
||||
],
|
||||
'Parent directory does not exist' => [
|
||||
'previous' => '',
|
||||
'current' => '3.2.0',
|
||||
'first' => '3.0.0',
|
||||
'pattern' => $sTmpDir.DIRECTORY_SEPARATOR.'missing'.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml',
|
||||
'message' => 'parent directory',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare common context for LoadLocalizedData tests.
|
||||
*
|
||||
* @return array{0: Config, 1: string, 2: string, 3: string, 4: string}
|
||||
* @return array{0: Config, 1: string}
|
||||
*/
|
||||
private function GivenLocalizedDataTestContext(string $sOrgNamePrefix, string $sLanguage): array
|
||||
private function GivenLocalizedDataTestContext(string $sLanguage, string $sDataFileName = 'data.sample.organizations.en_us.xml', bool $bAssertFileExists = true): array
|
||||
{
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$oConfig->SetDefaultLanguage($sLanguage);
|
||||
$this->assertNotNull($oConfig);
|
||||
|
||||
$sOrgName = $sOrgNamePrefix.uniqid();
|
||||
$sPattern = __DIR__.DIRECTORY_SEPARATOR.'resources2'.DIRECTORY_SEPARATOR.'data'.DIRECTORY_SEPARATOR.'load-localized-data'.DIRECTORY_SEPARATOR.$sDataFileName;
|
||||
if ($bAssertFileExists) {
|
||||
$this->assertFileExists($sPattern);
|
||||
}
|
||||
|
||||
$sTmpDir = static::CreateTmpdir();
|
||||
$this->aFileToClean[] = $sTmpDir;
|
||||
$sPattern = $sTmpDir.DIRECTORY_SEPARATOR.'data.{{language_code}}.xml';
|
||||
|
||||
return [$oConfig, $sOrgName, $sTmpDir, $sPattern];
|
||||
return [$oConfig, $sPattern];
|
||||
}
|
||||
|
||||
private function GivenLocalizedDataFile(string $sDir, string $sLang, string $sOrgName): string
|
||||
private function AssertOrganizationNamesExist(array $aExpectedOrganizationNames): void
|
||||
{
|
||||
$sFilePath = $sDir.DIRECTORY_SEPARATOR.'data.'.$sLang.'.xml';
|
||||
file_put_contents($sFilePath, $this->BuildOrganizationXml($sOrgName, $sLang));
|
||||
|
||||
return $sFilePath;
|
||||
foreach ($aExpectedOrganizationNames as $sExpectedName) {
|
||||
$this->AssertOrganizationNameExists($sExpectedName);
|
||||
}
|
||||
}
|
||||
|
||||
private function BuildOrganizationXml(string $sOrgName, string $sLang): string
|
||||
{
|
||||
$iId = random_int(100000, 999999);
|
||||
$sOrgNameXml = htmlspecialchars($sOrgName, ENT_XML1);
|
||||
|
||||
return <<<XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Set>
|
||||
<Organization alias="Organization" id="{$iId}">
|
||||
<name>{$sOrgNameXml}</name>
|
||||
<code>{$sLang}</code>
|
||||
<status>active</status>
|
||||
</Organization>
|
||||
</Set>
|
||||
XML;
|
||||
}
|
||||
|
||||
private function AssertOrganizationCountByName(string $sOrgName, string $sLanguage, int $iExpectedCount): void
|
||||
private function AssertOrganizationNameExists(string $sExpectedName): void
|
||||
{
|
||||
$oSet = new \DBObjectSet(
|
||||
\DBSearch::FromOQL("SELECT Organization WHERE name = :org_name AND code = :language"),
|
||||
\DBSearch::FromOQL("SELECT Organization WHERE name = :org_name"),
|
||||
[],
|
||||
['org_name' => $sOrgName, 'language' => $sLanguage]
|
||||
['org_name' => $sExpectedName]
|
||||
);
|
||||
$iCount = $oSet->Count();
|
||||
$this->assertEquals($iExpectedCount, $iCount, "Found $iCount changes for objects with name '{$sOrgName}' and language '{$sLanguage}', expected {$iExpectedCount}");
|
||||
$this->assertEquals(1, $oSet->Count(), "Expected exactly one Organization named '{$sExpectedName}'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,6 +49,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => false,
|
||||
'disabled' => false,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A selected but not installed extension should be checked and enabled' => [
|
||||
@@ -70,6 +72,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => false,
|
||||
'disabled' => false,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A missing extension should be disabled and unchecked' => [
|
||||
@@ -89,6 +93,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => true,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A missing extension should always be disabled and unchecked, even when mandatory' => [
|
||||
@@ -108,6 +114,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => true,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => true,
|
||||
],
|
||||
],
|
||||
'A missing extension should always be disabled and unchecked, even when non-uninstallable' => [
|
||||
@@ -127,6 +135,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => true,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => true,
|
||||
],
|
||||
],
|
||||
'An installed but not selected extension should not be checked and be enabled' => [
|
||||
@@ -148,6 +158,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => false,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'An installed non uninstallable extension should be checked and disabled' => [
|
||||
@@ -169,6 +181,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => true,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'An installed non uninstallable extension should be enabled if the "disable uninstallation check" flag is set' => [
|
||||
@@ -190,6 +204,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => false,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A mandatory extension should be checked and disabled' => [
|
||||
@@ -211,6 +227,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => false,
|
||||
'disabled' => true,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => true,
|
||||
],
|
||||
],
|
||||
'A mandatory extension should be checked and disabled even if the "disable uninstallation check" flag is set' => [
|
||||
@@ -232,6 +250,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => false,
|
||||
'disabled' => true,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => true,
|
||||
],
|
||||
],
|
||||
'An optional sub extension should not force its parent flags' => [
|
||||
@@ -265,6 +285,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => false,
|
||||
'disabled' => false,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A mandatory sub extension should force its parent to be checked and disabled' => [
|
||||
@@ -298,6 +320,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => false,
|
||||
'disabled' => true,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'An installed non uninstallable sub extension should force its parent to be checked and disabled' => [
|
||||
@@ -331,6 +355,8 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => true,
|
||||
'checked' => true,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A non installed non uninstallable sub extension should not force its parent flags' => [
|
||||
@@ -364,6 +390,62 @@ class WizStepModulesChoiceTest extends ItopTestCase
|
||||
'installed' => true,
|
||||
'disabled' => false,
|
||||
'checked' => false,
|
||||
'dependency_issue' => false,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'A non installed extension with missing dependencies should be not checked and disabled' => [
|
||||
'aExtensionsOnDiskOrDb' => [
|
||||
'itop-ext1' => [
|
||||
'installed' => false,
|
||||
'missing_dependencies' => [
|
||||
'itop-ext1-1',
|
||||
],
|
||||
],
|
||||
],
|
||||
'aWizardStepDefinition' => [
|
||||
'extension_code' => 'itop-ext1',
|
||||
'mandatory' => false,
|
||||
'uninstallable' => true,
|
||||
'missing_dependencies' => true,
|
||||
],
|
||||
'bCurrentSelected' => false,
|
||||
'bDisableUninstallChecks' => false,
|
||||
'aExpectedFlags' => [
|
||||
'uninstallable' => true,
|
||||
'missing' => false,
|
||||
'installed' => false,
|
||||
'disabled' => true,
|
||||
'checked' => false,
|
||||
'dependency_issue' => true,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
'An installed extension with missing dependencies should be not checked and disabled' => [
|
||||
'aExtensionsOnDiskOrDb' => [
|
||||
'itop-ext1' => [
|
||||
'installed' => true,
|
||||
'missing_dependencies' => [
|
||||
'itop-ext1-1',
|
||||
],
|
||||
],
|
||||
],
|
||||
'aWizardStepDefinition' => [
|
||||
'extension_code' => 'itop-ext1',
|
||||
'mandatory' => false,
|
||||
'uninstallable' => true,
|
||||
'missing_dependencies' => true,
|
||||
],
|
||||
'bCurrentSelected' => false,
|
||||
'bDisableUninstallChecks' => false,
|
||||
'aExpectedFlags' => [
|
||||
'uninstallable' => true,
|
||||
'missing' => false,
|
||||
'installed' => true,
|
||||
'disabled' => true,
|
||||
'checked' => false,
|
||||
'dependency_issue' => true,
|
||||
'mandatory' => false,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
@@ -79,6 +79,7 @@ class SetupAuditTest extends ItopCustomDatamodelTestCase
|
||||
"Feature1Module1MyClass",
|
||||
"FinalClassFeature2Module1MyClass",
|
||||
"FinalClassFeature2Module1MyFinalClassFromLocation",
|
||||
"TagSetFieldDataFor_FinalClassFeature2Module1MyFinalClassFromLocation__domains",
|
||||
];
|
||||
$this->assertEqualsCanonicalizing($expected, $oSetupAudit->GetRemovedClasses());
|
||||
|
||||
|
||||
@@ -64,6 +64,12 @@
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<validation_pattern/>
|
||||
</field>
|
||||
<field id="domains" xsi:type="AttributeTagSet">
|
||||
<sql>domains</sql>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
<max_items>12</max_items>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation/>
|
||||
|
||||
@@ -31,6 +31,12 @@
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="domains" xsi:type="AttributeTagSet">
|
||||
<sql>domains</sql>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<tracking_level>all</tracking_level>
|
||||
<max_items>12</max_items>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation/>
|
||||
|
||||
@@ -23,6 +23,7 @@ class iTopExtensionsMapFake extends iTopExtensionsMap
|
||||
$oExtension->sVersion = $aExtension['version'] ?? '1.0.0';
|
||||
$oExtension->sSource = $aExtension['source'] ?? iTopExtension::SOURCE_MANUAL;
|
||||
$oExtension->aModuleInfo = $aExtension['module_info'] ?? [];
|
||||
$oExtension->aMissingDependencies = $aExtension['missing_dependencies'] ?? [];
|
||||
$oMap->AddExtension($oExtension);
|
||||
}
|
||||
return $oMap;
|
||||
|
||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user