mirror of
https://github.com/Combodo/iTop.git
synced 2026-08-01 03:18:18 +02:00
Compare commits
69 Commits
feature/63
...
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 | ||
|
|
556f612f7e | ||
|
|
edc69bebba | ||
|
|
dce1994b85 | ||
|
|
fde6527057 | ||
|
|
0de0592c18 | ||
|
|
c9d512cc31 | ||
|
|
a3ef049063 | ||
|
|
87ec702c5e | ||
|
|
127be1933d | ||
|
|
2c14030fc5 | ||
|
|
7825c08069 | ||
|
|
4ddf17233f | ||
|
|
9493bb03d5 | ||
|
|
8f87c759b5 | ||
|
|
348c90145d | ||
|
|
c37143176a | ||
|
|
0c8229a68e | ||
|
|
fda5fe5ded | ||
|
|
6b396adeea | ||
|
|
c448f8411c | ||
|
|
4b4fe55060 | ||
|
|
dedcd4af19 | ||
|
|
0556a03839 | ||
|
|
64df429715 | ||
|
|
9ae813db2b | ||
|
|
768423a6aa | ||
|
|
921e7c88fe | ||
|
|
d6ef4fb7bb | ||
|
|
a335e1004b | ||
|
|
e882df96d9 | ||
|
|
3a7439e970 | ||
|
|
7fca6424ab | ||
|
|
f09a73c45a | ||
|
|
5a174dd8fa | ||
|
|
01f32086ec | ||
|
|
5c59fdebaf | ||
|
|
363d0767d5 | ||
|
|
5202adb902 | ||
|
|
1d9e7f9b55 |
5
.github/pull_request_template.md
vendored
5
.github/pull_request_template.md
vendored
@@ -9,11 +9,6 @@ Any PRs not following the guidelines or with missing information will not be con
|
||||
|
||||
## Base information
|
||||
|
||||
| Question | Answer
|
||||
|----------------------------------------------------------------|--------
|
||||
| Related to a SourceForge thread / Another PR / A GitHub Issue / Combodo ticket? | <!-- Put the URL --> |
|
||||
| Type of change? | Bug fix / Enhancement / Translations
|
||||
|
||||
| Question | Answer |
|
||||
|---------------------------------------------------------------------------------|--------------------------------------|
|
||||
| Related to a SourceForge thread / Another PR / A GitHub Issue / Combodo ticket? | <!-- Put the URL --> |
|
||||
|
||||
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
@@ -582,16 +582,26 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
*/
|
||||
public function ListProfiles($oUser)
|
||||
{
|
||||
$aRet = [];
|
||||
$oSearch = new DBObjectSearch('URP_UserProfile');
|
||||
$oSearch->AllowAllData();
|
||||
$oSearch->NoContextParameters();
|
||||
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
|
||||
$oProfiles = new DBObjectSet($oSearch);
|
||||
while ($oUserProfile = $oProfiles->Fetch()) {
|
||||
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
|
||||
if (count($oUser->ListChanges()) === 0) { // backward compatibility
|
||||
$aRet = [];
|
||||
$oSearch = new DBObjectSearch('URP_UserProfile');
|
||||
$oSearch->AllowAllData();
|
||||
$oSearch->NoContextParameters();
|
||||
$oSearch->Addcondition('userid', $oUser->GetKey(), '=');
|
||||
$oProfiles = new DBObjectSet($oSearch);
|
||||
while ($oUserProfile = $oProfiles->Fetch()) {
|
||||
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
|
||||
}
|
||||
|
||||
return $aRet;
|
||||
} else {
|
||||
$aRet = [];
|
||||
$oProfilesSet = $oUser->Get('profile_list');
|
||||
foreach ($oProfilesSet as $oUserProfile) {
|
||||
$aRet[$oUserProfile->Get('profileid')] = $oUserProfile->Get('profileid_friendlyname');
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
return $aRet;
|
||||
}
|
||||
|
||||
public function GetSelectFilter($oUser, $sClass, $aSettings = [])
|
||||
@@ -705,26 +715,23 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
protected function GetUserActionGrant($oUser, $sClass, $iActionCode)
|
||||
{
|
||||
$this->LoadCache();
|
||||
|
||||
// load and cache permissions for the current user on the given class
|
||||
//
|
||||
$iUser = $oUser->GetKey();
|
||||
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])) {
|
||||
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
||||
if (is_array($aTest)) {
|
||||
return $aTest;
|
||||
if (count($oUser->ListChanges()) === 0) {
|
||||
// load and cache permissions for the current user on the given class
|
||||
if (isset($this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iActionCode])) {
|
||||
$aTest = $this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iActionCode];
|
||||
if (is_array($aTest)) {
|
||||
return $aTest;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||
|
||||
$bStatus = null;
|
||||
// Cache user's profiles
|
||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
}
|
||||
|
||||
$aProfileList = $this->GetProfileList($oUser);
|
||||
// Call the API of UserRights because it caches the list for us
|
||||
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
|
||||
foreach ($aProfileList as $iProfile => $oProfile) {
|
||||
$bGrant = $this->GetProfileActionGrant($iProfile, $sClass, $sAction);
|
||||
if (!is_null($bGrant)) {
|
||||
if ($bGrant) {
|
||||
@@ -742,7 +749,9 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$aRes = [
|
||||
'permission' => $iPermission,
|
||||
];
|
||||
$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode] = $aRes;
|
||||
if (count($oUser->ListChanges()) === 0) {
|
||||
$this->m_aObjectActionGrants[$oUser->GetKey()][$sClass][$iActionCode] = $aRes;
|
||||
}
|
||||
return $aRes;
|
||||
}
|
||||
|
||||
@@ -824,18 +833,14 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
{
|
||||
$this->LoadCache();
|
||||
// Note: this code is VERY close to the code of IsActionAllowed()
|
||||
$iUser = $oUser->GetKey();
|
||||
|
||||
// Cache user's profiles
|
||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
||||
$this->aUsersProfilesList[$iUser] = UserRights::ListProfiles($oUser);
|
||||
}
|
||||
$aProfileList = $this->GetProfileList($oUser);
|
||||
|
||||
// Note: The object set is ignored because it was interesting to optimize for huge data sets
|
||||
// and acceptable to consider only the root class of the object set
|
||||
$bStatus = null;
|
||||
// Call the API of UserRights because it caches the list for us
|
||||
foreach ($this->aUsersProfilesList[$iUser] as $iProfile => $oProfile) {
|
||||
foreach ($aProfileList as $iProfile => $oProfile) {
|
||||
$bGrant = $this->GetClassStimulusGrant($iProfile, $sClass, $sStimulusCode);
|
||||
if (!is_null($bGrant)) {
|
||||
if ($bGrant) {
|
||||
@@ -893,6 +898,25 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
}
|
||||
return $bHasSharing;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \User $oUser
|
||||
*
|
||||
* @return array
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetProfileList(User $oUser): array
|
||||
{
|
||||
if (count($oUser->ListChanges()) === 0) { // if user is already in db and not changed
|
||||
$iUser = $oUser->GetKey();
|
||||
if (false === array_key_exists($iUser, $this->aUsersProfilesList)) {
|
||||
$aProfiles = UserRights::ListProfiles($oUser);
|
||||
$this->aUsersProfilesList[$iUser] = $aProfiles;
|
||||
}
|
||||
return $this->aUsersProfilesList[$iUser];
|
||||
}
|
||||
return UserRights::ListProfiles($oUser);
|
||||
}
|
||||
}
|
||||
|
||||
UserRights::SelectModule('UserRightsProfile');
|
||||
|
||||
@@ -113,17 +113,43 @@ abstract class Query extends cmdbAbstractObject
|
||||
]
|
||||
));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey(
|
||||
"owner_id",
|
||||
[
|
||||
"targetclass" => 'Contact',
|
||||
"allowed_values" => null,
|
||||
"sql" => 'owner_id',
|
||||
"is_null_allowed" => true,
|
||||
"depends_on" => [],
|
||||
"display_style" => 'select',
|
||||
"always_load_in_tables" => false,
|
||||
"on_target_delete" => DEL_AUTO,
|
||||
]
|
||||
));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeEnumSet(
|
||||
"usages",
|
||||
[
|
||||
"allowed_values" => null,
|
||||
"possible_values" => new ValueSetEnumPadded("export,reference,notif,draft,dashlet"),
|
||||
"sql" => "usages",
|
||||
"depends_on" => [],
|
||||
"is_null_allowed" => true,
|
||||
"max_items" => 12,
|
||||
]
|
||||
));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems(
|
||||
'details',
|
||||
['name', 'is_template', 'description']
|
||||
['name', 'is_template', 'owner_id', 'usages', 'description']
|
||||
); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('list', ['description', 'usages']); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search', ['name', 'description', 'is_template']); // Criteria of the std search form
|
||||
MetaModel::Init_SetZListItems(
|
||||
'default_search',
|
||||
['name', 'description', 'is_template']
|
||||
['name', 'description', 'is_template', 'owner_id', 'usages']
|
||||
); // Criteria of the default search form
|
||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||
}
|
||||
@@ -143,6 +169,15 @@ abstract class Query extends cmdbAbstractObject
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
|
||||
public function GetInitialStateAttributeFlags($sAttCode, &$aReasons = [])
|
||||
{
|
||||
// read only attribute
|
||||
if (in_array($sAttCode, ['export_count', 'export_last_date', 'export_last_user_id'])) {
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
return parent::GetInitialStateAttributeFlags($sAttCode, $aReasons);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return export url.
|
||||
*
|
||||
@@ -214,15 +249,15 @@ class QueryOQL extends Query
|
||||
MetaModel::Init_SetZListItems(
|
||||
'details',
|
||||
[
|
||||
'col:col1' => ['fieldset:Query:baseinfo' => ['name', 'is_template', 'description', 'oql', 'fields']],
|
||||
'col:col1' => ['fieldset:Query:baseinfo' => ['name', 'is_template', 'owner_id', 'usages', 'description', 'oql', 'fields']],
|
||||
'col:col2' => ['fieldset:Query:exportInfo' => ['export_count', 'export_last_date', 'export_last_user_id', 'export_last_user_contact']],
|
||||
]
|
||||
); // Attributes to be displayed for the complete details
|
||||
MetaModel::Init_SetZListItems('list', ['description']); // Attributes to be displayed for a list
|
||||
MetaModel::Init_SetZListItems('list', ['description', 'usages']); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems(
|
||||
'standard_search',
|
||||
['name', 'description', 'is_template', 'fields', 'oql']
|
||||
['name', 'description', 'is_template', 'owner_id', 'usages', 'oql']
|
||||
); // Criteria of the std search form
|
||||
}
|
||||
|
||||
|
||||
@@ -284,8 +284,7 @@ class UIExtKeyWidget
|
||||
if ($bAddingValue) {
|
||||
$aArguments = [];
|
||||
foreach ($aAdditionalField as $sAdditionalField) {
|
||||
$oAttrDef = MetaModel::GetAttributeDef(get_class($oObj), $sAdditionalField);
|
||||
array_push($aArguments, $oAttrDef->GetValueLabel($oObj->Get($sAdditionalField)));
|
||||
array_push($aArguments, $oObj->Get($sAdditionalField));
|
||||
}
|
||||
$aOption['additional_field'] = utils::HtmlEntities(utils::VSprintf($sFormatAdditionalField, $aArguments));
|
||||
}
|
||||
|
||||
14
composer.lock
generated
14
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "1cca58a0e26794fb9c546a001f7f7de8",
|
||||
"content-hash": "24e7507794b971955358df5f2b143ac4",
|
||||
"packages": [
|
||||
{
|
||||
"name": "apereo/phpcas",
|
||||
@@ -5570,16 +5570,16 @@
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v3.24.0",
|
||||
"version": "v3.28.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/twigphp/Twig.git",
|
||||
"reference": "a6769aefb305efef849dc25c9fd1653358c148f0"
|
||||
"reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0",
|
||||
"reference": "a6769aefb305efef849dc25c9fd1653358c148f0",
|
||||
"url": "https://api.github.com/repos/twigphp/Twig/zipball/597c12ed286fb9d1701a36684ce6e0cbe28ebc8b",
|
||||
"reference": "597c12ed286fb9d1701a36684ce6e0cbe28ebc8b",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
@@ -5634,7 +5634,7 @@
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/twigphp/Twig/issues",
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.24.0"
|
||||
"source": "https://github.com/twigphp/Twig/tree/v3.28.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
@@ -5646,7 +5646,7 @@
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2026-03-17T21:31:11+00:00"
|
||||
"time": "2026-07-03T20:44:34+00:00"
|
||||
}
|
||||
],
|
||||
"packages-dev": [
|
||||
|
||||
@@ -916,7 +916,9 @@ class CMDBSource
|
||||
$aColumn = [];
|
||||
$aData = self::QueryToArray($sSql);
|
||||
foreach ($aData as $aRow) {
|
||||
@$aColumn[] = $aRow[$col];
|
||||
if ($aRow[$col] !== null) {
|
||||
$aColumn[] = $aRow[$col];
|
||||
}
|
||||
}
|
||||
return $aColumn;
|
||||
}
|
||||
|
||||
@@ -1935,9 +1935,8 @@ class DBObjectSearch extends DBSearch
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return DBObjectSearch
|
||||
*/
|
||||
protected function ApplyDataFilters(): DBObjectSearch
|
||||
protected function ApplyDataFilters(): DBSearch
|
||||
{
|
||||
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
|
||||
return $this;
|
||||
|
||||
@@ -676,9 +676,8 @@ class DBUnionSearch extends DBSearch
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return DBUnionSearch
|
||||
*/
|
||||
protected function ApplyDataFilters(): DBUnionSearch
|
||||
protected function ApplyDataFilters(): DBSearch
|
||||
{
|
||||
if ($this->IsAllDataAllowed() || $this->IsDataFiltered()) {
|
||||
return $this;
|
||||
|
||||
@@ -434,7 +434,7 @@ JS
|
||||
* Resize an image so that it fits the maximum width/height defined in the config file
|
||||
* @param ormDocument $oImage The original image stored as an array (content / mimetype / filename)
|
||||
* @return ormDocument The resampled image (or the original one if it already fit)
|
||||
* @deprecated since 3.3.0 Replaced by ormDocument::ResizeImageToFit
|
||||
* @deprecated 3.3.0 Use ormDocument::ResizeImageToFit instead
|
||||
*/
|
||||
public static function ResizeImageToFit(ormDocument $oImage, &$aDimensions = null)
|
||||
{
|
||||
|
||||
@@ -614,6 +614,13 @@ class LogChannels
|
||||
* @since 3.2.0
|
||||
*/
|
||||
public const SECURITY = 'Security';
|
||||
|
||||
/**
|
||||
* For Session parameters
|
||||
*
|
||||
* @Since 3.3.0
|
||||
*/
|
||||
public const SESSION_PARAMETERS = 'SessionParameters';
|
||||
}
|
||||
|
||||
abstract class LogAPI
|
||||
|
||||
@@ -5761,36 +5761,37 @@ abstract class MetaModel
|
||||
|
||||
self::$m_sEnvironment = $sEnvironment;
|
||||
|
||||
try {
|
||||
if (!defined('MODULESROOT')) {
|
||||
define('MODULESROOT', APPROOT.'env-'.self::$m_sEnvironment.'/');
|
||||
if (!defined('MODULESROOT')) {
|
||||
define('MODULESROOT', APPROOT.'env-'.self::$m_sEnvironment.'/');
|
||||
|
||||
self::$m_bTraceSourceFiles = $bTraceSourceFiles;
|
||||
self::$m_bTraceSourceFiles = $bTraceSourceFiles;
|
||||
|
||||
// $config can be either a filename, or a Configuration object (volatile!)
|
||||
if ($config instanceof Config) {
|
||||
self::LoadConfig($config, $bAllowCache);
|
||||
} else {
|
||||
self::LoadConfig(new Config($config), $bAllowCache);
|
||||
}
|
||||
|
||||
if ($bModelOnly) {
|
||||
return;
|
||||
}
|
||||
// $config can be either a filename, or a Configuration object (volatile!)
|
||||
if ($config instanceof Config) {
|
||||
self::LoadConfig($config, $bAllowCache);
|
||||
} else {
|
||||
self::LoadConfig(new Config($config), $bAllowCache);
|
||||
}
|
||||
|
||||
CMDBSource::SelectDB(self::$m_sDBName);
|
||||
|
||||
foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
|
||||
$oPHPClass::OnMetaModelStarted();
|
||||
if ($bModelOnly) {
|
||||
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
|
||||
EventService::InitService();
|
||||
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
|
||||
return;
|
||||
}
|
||||
|
||||
ExpressionCache::Warmup();
|
||||
} finally {
|
||||
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
|
||||
EventService::InitService();
|
||||
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
|
||||
}
|
||||
|
||||
CMDBSource::SelectDB(self::$m_sDBName);
|
||||
|
||||
foreach (MetaModel::EnumPlugins('ModuleHandlerApiInterface') as $oPHPClass) {
|
||||
$oPHPClass::OnMetaModelStarted();
|
||||
}
|
||||
|
||||
ExpressionCache::Warmup();
|
||||
|
||||
// Event service must be initialized after the MetaModel startup, otherwise it cannot discover classes implementing the iEventServiceSetup interface
|
||||
EventService::InitService();
|
||||
EventService::FireEvent(new EventData(ApplicationEvents::APPLICATION_EVENT_METAMODEL_STARTED));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -408,7 +408,7 @@ class ormDocument
|
||||
* @param int $iMaxImageHeight Maximum height for the resized image
|
||||
* @param array|null $aFinalDimensions Image dimensions after resizing or null if unable to read the image
|
||||
* @return ormDocument The resampled image
|
||||
*
|
||||
* @since 3.3.0 N°3124
|
||||
*/
|
||||
public function ResizeImageToFit(int $iMaxWidth, int $iMaxHeight, array|null &$aFinalDimensions = null): static
|
||||
{
|
||||
|
||||
@@ -39,7 +39,7 @@ abstract class Trigger extends cmdbAbstractObject
|
||||
"category" => "grant_by_profile,core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger",
|
||||
@@ -174,7 +174,7 @@ abstract class TriggerOnObject extends Trigger
|
||||
"category" => "grant_by_profile,core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobject",
|
||||
@@ -401,7 +401,7 @@ class TriggerOnPortalUpdate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onportalupdate",
|
||||
@@ -434,7 +434,7 @@ abstract class TriggerOnStateChange extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onstatechange",
|
||||
@@ -469,7 +469,7 @@ class TriggerOnStateEnter extends TriggerOnStateChange
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onstateenter",
|
||||
@@ -503,7 +503,7 @@ class TriggerOnStateLeave extends TriggerOnStateChange
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onstateleave",
|
||||
@@ -537,7 +537,7 @@ class TriggerOnObjectCreate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjcreate",
|
||||
@@ -572,7 +572,7 @@ class TriggerOnObjectDelete extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjdelete",
|
||||
@@ -607,7 +607,7 @@ class TriggerOnObjectUpdate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjupdate",
|
||||
@@ -695,7 +695,7 @@ class TriggerOnObjectMention extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onobjmention",
|
||||
@@ -773,7 +773,7 @@ class TriggerOnAttributeBlobDownload extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattblobdownload",
|
||||
@@ -852,7 +852,7 @@ class TriggerOnThresholdReached extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_threshold",
|
||||
|
||||
@@ -1530,6 +1530,37 @@ class UserRights
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param User $oUser
|
||||
* @param array $aExcludedProfilesId Administrator by default, but can also be other proofiles depending on needs (e.g. power portal user or REST profile)
|
||||
* @return bool
|
||||
* @throws ArchivedObjectException
|
||||
* @throws CoreException
|
||||
* @throws CoreUnexpectedValue
|
||||
* @throws MySQLException
|
||||
*/
|
||||
public static function IsUserReadOnly(User $oUser, array $aExcludedProfilesId = [1]): bool
|
||||
{
|
||||
$oUserProfiles = $oUser->Get('profile_list');
|
||||
$oUserRights = UserRights::GetModuleInstance();
|
||||
while ($oUserProfile = $oUserProfiles->Fetch()) {
|
||||
$iProfileId = $oUserProfile->Get('profileid');
|
||||
if (in_array($iProfileId, $aExcludedProfilesId)) {
|
||||
return false;
|
||||
}
|
||||
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass) {
|
||||
foreach (['w', 'bw', 'd', 'bd'] as $sWriteActionCode) {
|
||||
$bIsGranted = $oUserRights->GetProfileActionGrant($iProfileId, $sClass, $sWriteActionCode);
|
||||
if ($bIsGranted === true) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param int $iActionCode see UR_ACTION_* constants
|
||||
|
||||
@@ -404,8 +404,7 @@ class ValueSetObjects extends ValueSetDefinition
|
||||
if (count($aAdditionalField) > 0) {
|
||||
$aArguments = [];
|
||||
foreach ($aAdditionalField as $sAdditionalField) {
|
||||
$oAttrDef = MetaModel::GetAttributeDef(get_class($oObject), $sAdditionalField);
|
||||
array_push($aArguments, $oAttrDef->GetValueLabel($oObject->Get($sAdditionalField)));
|
||||
array_push($aArguments, $oObject->Get($sAdditionalField));
|
||||
}
|
||||
$aData['additional_field'] = utils::VSprintf($sFormatAdditionalField, $aArguments);
|
||||
} else {
|
||||
|
||||
@@ -19,6 +19,8 @@ $ibo-badge-colors: (
|
||||
'orange' : ($ibo-color-orange-100, $ibo-color-orange-900),
|
||||
'red': ($ibo-color-red-100, $ibo-color-red-900),
|
||||
'pink': ($ibo-color-pink-100, $ibo-color-pink-900),
|
||||
'purple': ($ibo-color-purple-100, $ibo-color-purple-900),
|
||||
'yellow': ($ibo-color-yellow-200, $ibo-color-yellow-900),
|
||||
) !default;
|
||||
|
||||
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
$ibo-input-select-icon--menu--icon--max-height: 100% !default;
|
||||
$ibo-input-select-icon--menu--icon--max-width: 100% !default;
|
||||
$ibo-input-select-icon--icon--padding-right: $ibo-spacing-200 !default;
|
||||
$ibo-input-select-icon--max-height: 100% !default;
|
||||
$ibo-input-select-icon--max-width: 100% !default;
|
||||
$ibo-input-select-icon--padding-right: $ibo-spacing-200 !default;
|
||||
|
||||
$ibo-input-select-icon--menu--z-index: 21 !default;
|
||||
$ibo-input-select-icon--menu--max-height: 300px !default;
|
||||
@@ -18,9 +18,9 @@ $ibo-input-select-icon--menu--icon--margin-right: 10px !default;
|
||||
display: inline-flex;
|
||||
text-align: left;
|
||||
>img{
|
||||
max-height: $ibo-input-select-icon--menu--icon--max-height;
|
||||
max-width: $ibo-input-select-icon--menu--icon--max-width;
|
||||
padding-right: $ibo-input-select-icon--icon--padding-right;
|
||||
max-height: $ibo-input-select-icon--max-height;
|
||||
max-width: $ibo-input-select-icon--max-width;
|
||||
padding-right: $ibo-input-select-icon--padding-right;
|
||||
}
|
||||
>span{
|
||||
overflow: hidden;
|
||||
|
||||
@@ -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
@@ -611,32 +611,6 @@ body {
|
||||
.setup-extension--missing .setup-extension--icon{
|
||||
color:#a00000;
|
||||
}
|
||||
.setup-extension-tag {
|
||||
display: inline-flex;
|
||||
background-color: grey;
|
||||
border-radius: 8px;
|
||||
padding-left: 3px;
|
||||
padding-right: 3px;
|
||||
margin-right: 3px;
|
||||
&.installed{
|
||||
background-color:#9eff9e
|
||||
}
|
||||
&.notinstalled{
|
||||
background-color:#ed9eff
|
||||
}
|
||||
&.tobeinstalled{
|
||||
background-color:#9ef0ff
|
||||
}
|
||||
&.tobeuninstalled{
|
||||
background-color:#ff9e9e
|
||||
}
|
||||
&.notuninstallable{
|
||||
background-color:#ffc98c
|
||||
}
|
||||
&.removed{
|
||||
background-color: #969594
|
||||
}
|
||||
}
|
||||
|
||||
.ibo-extension-details {
|
||||
align-items: flex-start;
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Controller;
|
||||
|
||||
require_once APPROOT.'setup/feature_removal/SetupAudit.php';
|
||||
require_once APPROOT.'setup/feature_removal/DryRemovalRuntimeEnvironment.php';
|
||||
|
||||
use Combodo\iTop\Application\Helper\Session;
|
||||
use Combodo\iTop\Application\TwigBase\Controller\Controller;
|
||||
@@ -18,7 +17,8 @@ use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalHelper;
|
||||
use Combodo\iTop\DataFeatureRemoval\Helper\DataFeatureRemovalLog;
|
||||
use Combodo\iTop\DataFeatureRemoval\Service\DataCleanupService;
|
||||
use Combodo\iTop\DataFeatureRemoval\Service\DataFeatureRemoverExtensionService;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\DryRemovalRuntimeEnvironment;
|
||||
use Combodo\iTop\DataFeatureRemoval\Service\StaticDeletionPlan;
|
||||
use Combodo\iTop\Service\Session\SessionParameters;
|
||||
use Combodo\iTop\Setup\FeatureRemoval\SetupAudit;
|
||||
use ContextTag;
|
||||
use CoreException;
|
||||
@@ -37,15 +37,18 @@ class DataFeatureRemovalController extends Controller
|
||||
private array $aCountClassesToCleanup = [];
|
||||
private array $aAnalysisDataTable = [];
|
||||
private array $aDeletionExecutionSummary = [];
|
||||
private ?RuntimeEnvironment $oRuntimeEnvironment = null;
|
||||
|
||||
private int $iCount = 0;
|
||||
private int $iColumnCount = 2;
|
||||
private RunTimeEnvironment $oRuntimeEnvironment;
|
||||
|
||||
public function OperationMain($sErrorMessage = null): void
|
||||
{
|
||||
$aParams = [];
|
||||
|
||||
SetupUtils::EraseSetupToken();
|
||||
(new SessionParameters(SetupUtils::SESSION_PARAMETERS_NAME))->Erase();
|
||||
|
||||
$this->AddAnalyzeParams();
|
||||
$aParams['sTransactionId'] = utils::GetNewTransactionId();
|
||||
$aParams['iColumnCount'] = $this->iColumnCount;
|
||||
@@ -124,9 +127,10 @@ class DataFeatureRemovalController extends Controller
|
||||
|
||||
$aRemovedExtensions = $this->aExtensionsToCheck['to_be_removed'];
|
||||
$aHiddenInputs['removed_extensions'] = $this->ConvertIntoSetupFormat($aRemovedExtensions);
|
||||
}
|
||||
|
||||
$aRemoveExtensionCodes = array_keys($aRemovedExtensions);
|
||||
$aExtensionsNotUninstallable = $this->aExtensionsToCheck['extensions_not_uninstallable'];
|
||||
$aHiddenInputs['extensions_not_uninstallable'] = $this->ConvertIntoSetupFormat($aExtensionsNotUninstallable);
|
||||
}
|
||||
|
||||
$aParams['aAddedExtensions'] = $aAddedExtensions;
|
||||
$aParams['aRemovedExtensions'] = $aRemovedExtensions;
|
||||
@@ -139,9 +143,24 @@ class DataFeatureRemovalController extends Controller
|
||||
$aParams['iColumnCount'] = $this->iColumnCount;
|
||||
$aParams['aAvailableExtensions'] = $this->SplitArrayIntoColumns($this->GetExtensionsDiff($aAddedExtensions, $aRemovedExtensions), $this->iColumnCount);
|
||||
|
||||
$bForceCompilation = Session::Get('bForceCompilation', false);
|
||||
//to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists)
|
||||
$sSourceEnv = MetaModel::GetEnvironment();
|
||||
$this->oRuntimeEnvironment = new RunTimeEnvironment($sSourceEnv, false);
|
||||
|
||||
if ('[]' === $aHiddenInputs['selected_modules']) {
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions));
|
||||
$aHiddenInputs['selected_extensions'] = $this->ConvertIntoSetupFormat($aSelectedExtensions);
|
||||
|
||||
$aSelectedModules = []; // keep it to compile method
|
||||
} else {
|
||||
$aSelectedExtensions = json_decode($aHiddenInputs['selected_extensions'], true);
|
||||
$aSelectedModules = json_decode($aHiddenInputs['selected_modules'], true);
|
||||
}
|
||||
|
||||
try {
|
||||
$this->Compile($aAddedExtensions, $aRemoveExtensionCodes, $bForceCompilation);
|
||||
$this->Compile($aSelectedExtensions, array_keys($aRemovedExtensions), $aSelectedModules);
|
||||
$aHiddenInputs['selected_modules'] = $this->ConvertIntoSetupFormat($aSelectedModules);
|
||||
} catch (CoreException $e) {
|
||||
$aParams['DataFeatureRemovalErrorMessage'] = $e->getHtmlDesc();
|
||||
$this->DisplayPage($aParams, 'AnalysisResult');
|
||||
@@ -152,19 +171,6 @@ class DataFeatureRemovalController extends Controller
|
||||
return;
|
||||
}
|
||||
|
||||
if ("[]" === $aHiddenInputs['selected_modules']) {
|
||||
//to make setup redirection work, we need to pass complex data structures to setup wizards (ie extension/module lists)
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
$aSelectedExtensions = DataFeatureRemoverExtensionService::GetInstance()->GetExtensionMap()->GetSelectedExtensions($oConfig, array_keys($aAddedExtensions), array_keys($aRemovedExtensions));
|
||||
$aHiddenInputs['selected_extensions'] = $this->ConvertIntoSetupFormat($aSelectedExtensions);
|
||||
|
||||
$oRunTimeEnvironment = $this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions);
|
||||
$aSearchDirs = [$oRunTimeEnvironment->GetBuildDir()];
|
||||
$aSelectedModules = $oRunTimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions, $aSearchDirs);
|
||||
$aHiddenInputs['selected_modules'] = $this->ConvertIntoSetupFormat($aSelectedModules);
|
||||
}
|
||||
|
||||
$sSourceEnv = MetaModel::GetEnvironment();
|
||||
$oSetupAudit = new SetupAudit($sSourceEnv);
|
||||
$aGetRemovedClasses = array_keys($oSetupAudit->RunDataAudit());
|
||||
DataFeatureRemovalLog::Debug(__METHOD__, null, ['aGetRemovedClasses' => $aGetRemovedClasses]);
|
||||
@@ -179,7 +185,7 @@ class DataFeatureRemovalController extends Controller
|
||||
];
|
||||
|
||||
foreach ($aHiddenInputs as $sInputName => $sInputValue) {
|
||||
$aParams['aSetupParams']["_params[$sInputName]"] = $sInputValue;
|
||||
$aParams['aSetupParams'][$sInputName] = $sInputValue;
|
||||
}
|
||||
|
||||
[$aParams['aDeletionPlanSummary'], $aParams['iQueryCount'], $aParams['bDeletionPossible']] = $this->GetDeletionPlanSummaryTable($aGetRemovedClasses);
|
||||
@@ -188,6 +194,7 @@ class DataFeatureRemovalController extends Controller
|
||||
Session::Set('aDeletionExecutionSummary', serialize($this->aDeletionExecutionSummary));
|
||||
|
||||
if (!$aParams['bDeletionNeeded']) {
|
||||
// Erase session setup parameters
|
||||
SetupUtils::CreateSetupToken();
|
||||
}
|
||||
|
||||
@@ -205,14 +212,15 @@ class DataFeatureRemovalController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aAddedExtensions
|
||||
* @param array $aRemovedExtensions
|
||||
* @param bool $bForceCompilation
|
||||
* @return void
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
* @param array $aSelectedExtensions
|
||||
* @param array $aRemovedExtensions
|
||||
* @param array $aSelectedModules
|
||||
*
|
||||
* @return void
|
||||
* @throws \ConfigException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
private function Compile(array $aAddedExtensions, array $aRemovedExtensions, bool $bForceCompilation = true): void
|
||||
private function Compile(array $aSelectedExtensions, array $aRemovedExtensions, array &$aSelectedModules): void
|
||||
{
|
||||
$sSourceEnv = MetaModel::GetEnvironment();
|
||||
$sBuildDir = APPROOT."/env-$sSourceEnv-build";
|
||||
@@ -220,27 +228,28 @@ class DataFeatureRemovalController extends Controller
|
||||
SetupUtils::builddir($sBuildDir);
|
||||
}
|
||||
$bIsDirEmpty = count(scandir($sBuildDir)) === 2;
|
||||
$bForceCompilation = Session::Get('bForceCompilation', false);
|
||||
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
if ($bIsDirEmpty || $bForceCompilation) {
|
||||
Session::Unset('bForceCompilation');
|
||||
$this->oRuntimeEnvironment->CopySetupFiles();
|
||||
if (count($aSelectedModules) === 0) {
|
||||
$aSelectedModules = $this->oRuntimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions);
|
||||
}
|
||||
DataFeatureRemovalLog::Debug(
|
||||
__METHOD__,
|
||||
null,
|
||||
['sSourceEnv' => $sSourceEnv, 'sBuildDir' => $sBuildDir, 'bIsDirEmpty' => $bIsDirEmpty, glob("$sBuildDir/*")]
|
||||
);
|
||||
$this->GetRuntimeEnvironment($aAddedExtensions, $aRemovedExtensions)->CompileFrom($sSourceEnv);
|
||||
$this->oRuntimeEnvironment->DoCompile($aSelectedExtensions, $aRemovedExtensions, $aSelectedModules, MFCompiler::CanUseSymbolicLinks());
|
||||
} else {
|
||||
if (count($aSelectedModules) === 0) {
|
||||
$aSelectedModules = $this->oRuntimeEnvironment->GetModulesToLoadFromChoices($oConfig, $aSelectedExtensions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function GetRuntimeEnvironment(array $aAddedExtensions, array $aRemovedExtensions): RunTimeEnvironment
|
||||
{
|
||||
if (is_null($this->oRuntimeEnvironment)) {
|
||||
$sSourceEnv = MetaModel::GetEnvironment();
|
||||
$this->oRuntimeEnvironment = new DryRemovalRuntimeEnvironment($sSourceEnv, $aAddedExtensions, $aRemovedExtensions);
|
||||
}
|
||||
|
||||
return $this->oRuntimeEnvironment;
|
||||
}
|
||||
|
||||
private function GetExecutionSummaryTable(): array
|
||||
{
|
||||
$sName = 'ExcutionSummary';
|
||||
@@ -272,7 +281,7 @@ class DataFeatureRemovalController extends Controller
|
||||
private function GetDeletionPlanSummaryTable(array $aRemovedClasses): array
|
||||
{
|
||||
$sName = 'DeletionPlanSummary';
|
||||
$oDataCleanupService = new DataCleanupService();
|
||||
$oDataCleanupService = new StaticDeletionPlan();
|
||||
$aDeletionPlanSummaryEntities = $oDataCleanupService->GetCleanupSummary($aRemovedClasses);
|
||||
$aColumns = ['Class', 'Delete Count' , 'Update Count', 'Issue Count'];
|
||||
$aRows = [];
|
||||
@@ -338,6 +347,7 @@ class DataFeatureRemovalController extends Controller
|
||||
'uninstallable' => $oExtension->CanBeUninstalled(),
|
||||
'remote' => $oExtension->IsRemote(),
|
||||
'missing' => $oExtension->bRemovedFromDisk,
|
||||
'dependency_issue' => $oExtension->HasDependencyIssue(),
|
||||
],
|
||||
|
||||
];
|
||||
@@ -418,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])) {
|
||||
@@ -431,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'];
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Entity;
|
||||
|
||||
class DeletionPlanEntity
|
||||
{
|
||||
public readonly DeletionPlanItem $oDelete;
|
||||
public readonly DeletionPlanItem $oUpdate;
|
||||
public readonly DeletionPlanItem $oIssue;
|
||||
|
||||
/**
|
||||
* @param \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem $oDelete
|
||||
* @param \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem $oUpdate
|
||||
* @param \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem $oIssue
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
$this->oDelete = $oDelete ?? new DeletionPlanItem();
|
||||
$this->oUpdate = $oUpdate ?? new DeletionPlanItem();
|
||||
$this->oIssue = $oIssue ?? new DeletionPlanItem();
|
||||
}
|
||||
|
||||
public function TotalCount(): int
|
||||
{
|
||||
return $this->oDelete->Count() + $this->oUpdate->Count() + $this->oIssue->Count();
|
||||
}
|
||||
|
||||
public function FilterUpdatesByDeletes()
|
||||
{
|
||||
$this->oUpdate->FilterBy($this->oDelete);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Entity;
|
||||
|
||||
class DeletionPlanItem
|
||||
{
|
||||
public array $aIds = [];
|
||||
|
||||
/**
|
||||
* @param array $aIds
|
||||
*/
|
||||
public function __construct(array $aIds = [])
|
||||
{
|
||||
$this->aIds = $aIds;
|
||||
}
|
||||
|
||||
public function Merge(DeletionPlanItem $oItem): void
|
||||
{
|
||||
$this->aIds = array_unique(array_merge($this->aIds, $oItem->aIds));
|
||||
}
|
||||
|
||||
public function Count(): int
|
||||
{
|
||||
return count($this->aIds);
|
||||
}
|
||||
|
||||
public function FilterBy(DeletionPlanItem $oItem): void
|
||||
{
|
||||
$this->aIds = array_diff($this->aIds, $oItem->aIds);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
@@ -0,0 +1,221 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2026 Combodo SAS
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
namespace Combodo\iTop\DataFeatureRemoval\Service;
|
||||
|
||||
use CMDBSource;
|
||||
use Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity;
|
||||
use Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanEntity;
|
||||
use Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem;
|
||||
use MetaModel;
|
||||
|
||||
class StaticDeletionPlan
|
||||
{
|
||||
/** @var array<DeletionPlanEntity> */
|
||||
private array $aDeletionPlan = [];
|
||||
|
||||
/**
|
||||
* Get a summary of the deletion plan computed for the classes.
|
||||
* The result is used for display
|
||||
*
|
||||
* @param array|null $aClasses
|
||||
*
|
||||
* @return array<\Combodo\iTop\DataFeatureRemoval\Entity\DataCleanupSummaryEntity>
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GetCleanupSummary(?array $aClasses): array
|
||||
{
|
||||
$aSummary = [];
|
||||
$aDeletionPlan = $this->GetStaticDeletionPlan($aClasses ?? []);
|
||||
|
||||
foreach ($aDeletionPlan as $sClass => $oDeletionPlanEntity) {
|
||||
if ($oDeletionPlanEntity->TotalCount() === 0) {
|
||||
continue;
|
||||
}
|
||||
$oDeletionPlanEntity->FilterUpdatesByDeletes();
|
||||
$oDataCleanupSummary = new DataCleanupSummaryEntity($sClass);
|
||||
$oDataCleanupSummary->iUpdateCount = $oDeletionPlanEntity->oUpdate->Count();
|
||||
$oDataCleanupSummary->iDeleteCount = $oDeletionPlanEntity->oDelete->Count();
|
||||
$oDataCleanupSummary->iIssueCount = $oDeletionPlanEntity->oIssue->Count();
|
||||
|
||||
$aSummary[$sClass] = $oDataCleanupSummary;
|
||||
}
|
||||
|
||||
return $aSummary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $aClasses Classes to clean entirely
|
||||
*
|
||||
* @return array ['class' => DeletionPlanEntity];
|
||||
*
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function GetStaticDeletionPlan(array $aClasses): array
|
||||
{
|
||||
foreach ($aClasses as $sClass) {
|
||||
$oDeletionPlanItem = $this->GetInitialClassDeletionPlan($sClass);
|
||||
// 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);
|
||||
}
|
||||
|
||||
return $this->aDeletionPlan;
|
||||
}
|
||||
|
||||
private function DeletionPlanForReferencingClasses(string $sClass): void
|
||||
{
|
||||
$sIdsToRemove = implode(', ', $this->aDeletionPlan[$sClass]->oDelete->aIds);
|
||||
$aReferencingMe = MetaModel::EnumReferencingClasses($sClass);
|
||||
foreach ($aReferencingMe as $sRemoteClass => $aExtKeys) {
|
||||
if (!isset($this->aDeletionPlan[$sRemoteClass])) {
|
||||
$this->aDeletionPlan[$sRemoteClass] = new DeletionPlanEntity();
|
||||
}
|
||||
$oDeletionPlanEntity = $this->aDeletionPlan[$sRemoteClass];
|
||||
/** @var \AttributeExternalKey $oExtKeyAttDef */
|
||||
foreach ($aExtKeys as $sExtKeyAttCode => $oExtKeyAttDef) {
|
||||
// skip if this external key is behind an external field
|
||||
if (!$oExtKeyAttDef->IsExternalKey(EXTKEY_ABSOLUTE)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($oExtKeyAttDef->IsNullAllowed()) {
|
||||
// update
|
||||
$oUpdateItem = $this->UpdateExtKeyNullable($sRemoteClass, $sExtKeyAttCode, $sIdsToRemove);
|
||||
$oDeletionPlanEntity->oUpdate->Merge($oUpdateItem);
|
||||
} else {
|
||||
// delete
|
||||
$aRemoteIdsToRemove = $this->GetRemoteIdsForExtKey($sRemoteClass, $sExtKeyAttCode, $sIdsToRemove);
|
||||
|
||||
$iDeletePropagationOption = $oExtKeyAttDef->GetDeletionPropagationOption();
|
||||
if ($iDeletePropagationOption == DEL_MANUAL) {
|
||||
// Issue, do not recurse
|
||||
$oDeletionPlanItem = new DeletionPlanItem(aIds: $aRemoteIdsToRemove);
|
||||
$oDeletionPlanEntity->oIssue->Merge($oDeletionPlanItem);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (($iDeletePropagationOption == DEL_MOVEUP) && ($oExtKeyAttDef->IsHierarchicalKey())) {
|
||||
// update hierarchical keys due to row cleanup in the same table
|
||||
$sTargetIdsToRemove = implode(',', $this->aDeletionPlan[$sRemoteClass]->oDelete->aIds);
|
||||
$oUpdateItem = $this->UpdateHierarchicalExtKey($sRemoteClass, $sExtKeyAttCode, $sTargetIdsToRemove);
|
||||
$oDeletionPlanEntity->oUpdate->Merge($oUpdateItem);
|
||||
}
|
||||
|
||||
// Delete entries in Remote Class
|
||||
if (count($aRemoteIdsToRemove) !== 0) {
|
||||
$oDeletionPlanEntity->oDelete->Merge(new DeletionPlanItem($aRemoteIdsToRemove));
|
||||
// Infinite loops do not occurs due to the datamodel structure
|
||||
$this->DeletionPlanForReferencingClasses($sRemoteClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRemoteClass
|
||||
* @param string $sExtKeyAttCode
|
||||
* @param string $sIdsToRemoveInTargetClass
|
||||
*
|
||||
* @return \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem
|
||||
* @throws \CoreException
|
||||
*/
|
||||
public function UpdateExtKeyNullable(string $sRemoteClass, string $sExtKeyAttCode, string $sIdsToRemoveInTargetClass): DeletionPlanItem
|
||||
{
|
||||
$aIds = $this->GetRemoteIdsForExtKey($sRemoteClass, $sExtKeyAttCode, $sIdsToRemoveInTargetClass);
|
||||
|
||||
return new DeletionPlanItem($aIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRemoteClass
|
||||
* @param string $sExtKeyAttCode
|
||||
* @param string $sIdsToRemoveInTargetClass
|
||||
*
|
||||
* @return \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function UpdateHierarchicalExtKey(string $sRemoteClass, string $sExtKeyAttCode, string $sIdsToRemoveInTargetClass): DeletionPlanItem
|
||||
{
|
||||
[$sDBTable, $sDBField, $sDBKey] = $this->GetDBInfoForAttcode($sRemoteClass, $sExtKeyAttCode);
|
||||
|
||||
$sSQL = <<<SQL
|
||||
SELECT `$sDBKey`
|
||||
FROM `$sDBTable` AS `updated`
|
||||
INNER JOIN `$sDBTable` AS `removed` ON `updated`.`$sDBField` = `removed`.`$sDBKey`
|
||||
WHERE `removed`.`$sDBKey` IN ($sIdsToRemoveInTargetClass)
|
||||
SQL;
|
||||
$aIds = CMDBSource::QueryToCol($sSQL, $sDBKey);
|
||||
|
||||
return new DeletionPlanItem($aIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sRemoteClass
|
||||
* @param string $sExtKeyAttCode
|
||||
* @param string $sIdsToRemoveInTargetClass
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function GetRemoteIdsForExtKey(string $sRemoteClass, string $sExtKeyAttCode, string $sIdsToRemoveInTargetClass): array
|
||||
{
|
||||
if (\utils::IsNullOrEmptyString($sIdsToRemoveInTargetClass)) {
|
||||
return [];
|
||||
}
|
||||
[$sDBTable, $sDBField, $sDBKey] = $this->GetDBInfoForAttcode($sRemoteClass, $sExtKeyAttCode);
|
||||
$sSQL = "SELECT `$sDBKey` FROM `$sDBTable` WHERE `$sDBField` IN ($sIdsToRemoveInTargetClass)";
|
||||
|
||||
return CMDBSource::QueryToCol($sSQL, $sDBKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sClass
|
||||
*
|
||||
* @return \Combodo\iTop\DataFeatureRemoval\Entity\DeletionPlanItem
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
*/
|
||||
public function GetInitialClassDeletionPlan(string $sClass): DeletionPlanItem
|
||||
{
|
||||
$sTable = MetaModel::DBGetTable($sClass);
|
||||
$sDBKey = MetaModel::DBGetKey($sClass);
|
||||
$sSQL = "SELECT `$sDBKey` FROM `$sTable`";
|
||||
$aIds = CMDBSource::QueryToCol($sSQL, $sDBKey);
|
||||
|
||||
return new DeletionPlanItem($aIds);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get database table for an attcode
|
||||
*
|
||||
* @param string $sClass
|
||||
* @param string $sExtKeyAttCode
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function GetDBInfoForAttcode(string $sClass, string $sExtKeyAttCode): array
|
||||
{
|
||||
$sOriginClass = MetaModel::GetAttributeOrigin($sClass, $sExtKeyAttCode);
|
||||
$sDBTable = MetaModel::DBGetTable($sOriginClass);
|
||||
$oAttDef = MetaModel::GetAttributeDef($sOriginClass, $sExtKeyAttCode);
|
||||
// External key is on a single DB column
|
||||
$sDBField = array_keys($oAttDef->GetSQLColumns())[0];
|
||||
$sDBKey = MetaModel::DBGetKey($sClass);
|
||||
return [$sDBTable, $sDBField, $sDBKey];
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,6 +8,8 @@ $baseDir = dirname($vendorDir);
|
||||
return array(
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => $baseDir . '/src/Controller/DataFeatureRemovalController.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DataCleanupSummaryEntity' => $baseDir . '/src/Entity/DataCleanupSummaryEntity.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanEntity' => $baseDir . '/src/Entity/DeletionPlanEntity.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanItem' => $baseDir . '/src/Entity/DeletionPlanItem.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalConfig' => $baseDir . '/src/Helper/DataFeatureRemovalConfig.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => $baseDir . '/src/Helper/DataFeatureRemovalException.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => $baseDir . '/src/Helper/DataFeatureRemovalHelper.php',
|
||||
@@ -16,6 +18,7 @@ return array(
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => $baseDir . '/src/Service/DataFeatureRemoverExtensionService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectService' => $baseDir . '/src/Service/ObjectService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectServiceSummary' => $baseDir . '/src/Service/ObjectServiceSummary.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\StaticDeletionPlan' => $baseDir . '/src/Service/StaticDeletionPlan.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\iObjectService' => $baseDir . '/src/Service/iObjectService.php',
|
||||
'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
@@ -23,6 +23,8 @@ class ComposerStaticInit4f96a7199e2c0d90e547333758b26464
|
||||
public static $classMap = array (
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Controller\\DataFeatureRemovalController' => __DIR__ . '/../..' . '/src/Controller/DataFeatureRemovalController.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DataCleanupSummaryEntity' => __DIR__ . '/../..' . '/src/Entity/DataCleanupSummaryEntity.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanEntity' => __DIR__ . '/../..' . '/src/Entity/DeletionPlanEntity.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Entity\\DeletionPlanItem' => __DIR__ . '/../..' . '/src/Entity/DeletionPlanItem.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalConfig' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalConfig.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalException' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalException.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Helper\\DataFeatureRemovalHelper' => __DIR__ . '/../..' . '/src/Helper/DataFeatureRemovalHelper.php',
|
||||
@@ -31,6 +33,7 @@ class ComposerStaticInit4f96a7199e2c0d90e547333758b26464
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\DataFeatureRemoverExtensionService' => __DIR__ . '/../..' . '/src/Service/DataFeatureRemoverExtensionService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectService' => __DIR__ . '/../..' . '/src/Service/ObjectService.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\ObjectServiceSummary' => __DIR__ . '/../..' . '/src/Service/ObjectServiceSummary.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\StaticDeletionPlan' => __DIR__ . '/../..' . '/src/Service/StaticDeletionPlan.php',
|
||||
'Combodo\\iTop\\DataFeatureRemoval\\Service\\iObjectService' => __DIR__ . '/../..' . '/src/Service/iObjectService.php',
|
||||
'Composer\\InstalledVersions' => __DIR__ . '/..' . '/composer/InstalledVersions.php',
|
||||
);
|
||||
|
||||
@@ -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',
|
||||
]);
|
||||
|
||||
@@ -24,7 +24,7 @@ class TriggerOnAttachmentCreate extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattcreate",
|
||||
|
||||
@@ -24,7 +24,7 @@ class TriggerOnAttachmentDelete extends TriggerOnObject
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattdelete",
|
||||
|
||||
@@ -19,7 +19,7 @@ class TriggerOnAttachmentDownload extends TriggerOnAttributeBlobDownload
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "description",
|
||||
"complementary_name_attcode" => ['finalclass', 'target_class'],
|
||||
"complementary_name_attcode" => ['finalclass', 'complement'],
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => ['description'],
|
||||
"db_table" => "priv_trigger_onattdownload",
|
||||
|
||||
@@ -21,11 +21,11 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Menu:SearchChanges' => 'Hledat změny',
|
||||
'Menu:SearchChanges+' => 'Hledat změnové tikety',
|
||||
'Menu:Change:Shortcuts' => 'Odkazy',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Změny čekající na přijetí',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Změny čekající na schválení',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Otevřené změny',
|
||||
'Menu:Changes+' => 'Všechny otevřené změny',
|
||||
'Menu:MyChanges' => 'Změny přidělené mně',
|
||||
|
||||
@@ -20,11 +20,11 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Menu:SearchChanges' => 'Søg efter Changes',
|
||||
'Menu:SearchChanges+' => 'Søg efter Change Tickets',
|
||||
'Menu:Change:Shortcuts' => 'Genveje',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes, som afventer accept',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes, som afventer godkendelse',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Offene Changes',
|
||||
'Menu:Changes+' => 'Alle åbne Changes',
|
||||
'Menu:MyChanges' => 'Mine Changes',
|
||||
|
||||
@@ -19,8 +19,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Menu:NewChange+' => 'Einen neuen Change erstellen',
|
||||
'Menu:SearchChanges' => 'Suche nach Changes',
|
||||
'Menu:SearchChanges+' => 'Unter den bestehenden Changes suchen',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts' => 'Changes~~',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes, die auf Annahme warten',
|
||||
'Menu:WaitingAcceptance+' => 'Changes, die auf Annahme warten',
|
||||
'Menu:WaitingApproval' => 'Changes, die auf Genehmigung warten',
|
||||
|
||||
@@ -30,16 +30,16 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Menu:NewChange+' => 'Create a new change ticket',
|
||||
'Menu:SearchChanges' => 'Search for changes',
|
||||
'Menu:SearchChanges+' => 'Search for change tickets',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts' => 'Changes',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes',
|
||||
'Menu:WaitingAcceptance' => 'Changes awaiting acceptance',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes awaiting approval',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status',
|
||||
'Menu:Changes' => 'Open changes',
|
||||
'Menu:Changes+' => 'All open changes',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status',
|
||||
'Menu:MyChanges' => 'Changes assigned to me',
|
||||
'Menu:MyChanges+' => 'Changes assigned to me (as Agent)',
|
||||
'Menu:MyChanges+' => 'Non-closed changes assigned to me (as an Agent)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changes by category for the last 7 days',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Number of changes for the last 7 days',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days',
|
||||
|
||||
@@ -30,16 +30,16 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Menu:NewChange+' => 'Create a new change ticket',
|
||||
'Menu:SearchChanges' => 'Search for changes',
|
||||
'Menu:SearchChanges+' => 'Search for change tickets',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts' => 'Changes~~',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes awaiting acceptance',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes awaiting approval',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Open changes',
|
||||
'Menu:Changes+' => 'All open changes',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status',
|
||||
'Menu:MyChanges' => 'Changes assigned to me',
|
||||
'Menu:MyChanges+' => 'Changes assigned to me (as Agent)',
|
||||
'Menu:MyChanges+' => 'Non-closed changes assigned to me (as an Agent)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changes by category for the last 7 days',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Number of changes for the last 7 days',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days',
|
||||
|
||||
@@ -18,16 +18,16 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Menu:NewChange+' => 'Créer un nouveau ticket de changement',
|
||||
'Menu:SearchChanges' => 'Rechercher des changements',
|
||||
'Menu:SearchChanges+' => 'Rechercher parmi les tickets de changement',
|
||||
'Menu:Change:Shortcuts' => 'Raccourcis',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Changements en attente d\'acceptance',
|
||||
'Menu:WaitingAcceptance+' => 'Changements en attente d\'acceptance',
|
||||
'Menu:WaitingApproval' => 'Changements en attente d\'approbation',
|
||||
'Menu:WaitingApproval+' => 'Changements en attente d\'approbation',
|
||||
'Menu:Changes' => 'Changements ouverts',
|
||||
'Menu:Changes+' => 'Tickets de changement ouverts',
|
||||
'Menu:MyChanges' => 'Mes changements',
|
||||
'Menu:MyChanges+' => 'Tickets de changement qui me sont assignés',
|
||||
'Menu:Change:Shortcuts' => 'Changements',
|
||||
'Menu:Change:Shortcuts+' => 'Raccourcis vers différents groupes de changements',
|
||||
'Menu:WaitingAcceptance' => 'En attente de validation',
|
||||
'Menu:WaitingAcceptance+' => 'Changements à l\'état nouveau, en attente d\'acceptation',
|
||||
'Menu:WaitingApproval' => 'En attente d\'approbation',
|
||||
'Menu:WaitingApproval+' => 'Changements dans l\'état programmé, en attente d\'approbation',
|
||||
'Menu:Changes' => 'En cours',
|
||||
'Menu:Changes+' => 'Tickets de changement qui ne sont pas dans l\'état fermé',
|
||||
'Menu:MyChanges' => 'Qui me sont assignés',
|
||||
'Menu:MyChanges+' => 'Changements ni fermés, ni résolus, dont je suis l\'agent assigné',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changements par catégorie',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Changements par jour',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changements par domaine',
|
||||
|
||||
@@ -19,11 +19,11 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Menu:SearchChanges' => 'Cerca per cambi',
|
||||
'Menu:SearchChanges+' => 'Cerca i cambi per tickets',
|
||||
'Menu:Change:Shortcuts' => 'Scorciatoie',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Modifiche in attesa di accettazione',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Modifiche in attesa di approvazione',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Modifiche aperte',
|
||||
'Menu:Changes+' => 'Tutte le Modifiche aperte',
|
||||
'Menu:MyChanges' => 'Modifiche assegnate a me',
|
||||
|
||||
@@ -19,13 +19,13 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'Menu:SearchChanges' => '変更検索',
|
||||
'Menu:SearchChanges+' => '変更チケット検索',
|
||||
'Menu:Change:Shortcuts' => 'ショートカット',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => '受理待ちの変更',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => '承認待ちの変更',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'オープン状態の変更',
|
||||
'Menu:Changes+' => '',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => '担当している変更',
|
||||
'Menu:MyChanges+' => '担当している変更(エージェントとして)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => '最近7日間のカテゴリ別の変更',
|
||||
|
||||
@@ -21,11 +21,11 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'Menu:SearchChanges' => 'Zoek naar changes',
|
||||
'Menu:SearchChanges+' => 'Zoek naar changes',
|
||||
'Menu:Change:Shortcuts' => 'Snelkoppelingen',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes die acceptatie vereisen',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes die goedkeuring vereisen',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Open changes',
|
||||
'Menu:Changes+' => 'Alle open changes',
|
||||
'Menu:MyChanges' => 'Changes toegewezen aan mij',
|
||||
|
||||
@@ -19,11 +19,11 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'Menu:SearchChanges' => 'Szukaj zmian',
|
||||
'Menu:SearchChanges+' => 'Szukaj zgłoszeń zmian',
|
||||
'Menu:Change:Shortcuts' => 'Skróty',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Zmiany do akceptacji',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Zmiany do zatwierdzenia',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Otwarte zmiany',
|
||||
'Menu:Changes+' => 'Wszystkie otwarte zmiany',
|
||||
'Menu:MyChanges' => 'Zmiany przypisane do mnie',
|
||||
|
||||
@@ -19,13 +19,13 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'Menu:SearchChanges' => 'Pesquisar por mudanças',
|
||||
'Menu:SearchChanges+' => 'Pesquisar por solicitações de mudança',
|
||||
'Menu:Change:Shortcuts' => 'Atalhos',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Mudanças aguardando aceitação',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Mudanças aguardando aprovação',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Mudanças abertas',
|
||||
'Menu:Changes+' => '',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => 'Mudanças atribuídas a mim',
|
||||
'Menu:MyChanges+' => 'Mudanças atribuídas a mim (como Agente)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Mudanças por categoria nos últimos 7 dias',
|
||||
|
||||
@@ -23,11 +23,11 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Menu:WaitingAcceptance' => 'Zmeny očakávajúce prijatie',
|
||||
'Menu:WaitingAcceptance+' => '~~',
|
||||
'Menu:WaitingApproval' => 'Zmeny očakávajúce schválenie',
|
||||
'Menu:WaitingApproval+' => '~~',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Otvorené zmeny',
|
||||
'Menu:Changes+' => 'All open changes~~',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => 'Zmeny pridelené mne',
|
||||
'Menu:MyChanges+' => 'Changes assigned to me (as Agent)~~',
|
||||
'Menu:MyChanges+' => 'Non-closed changes assigned to me (as an Agent)~~',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Zmeny podľa kategórie za posledných 7 dní',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Počet zmien za posledných 7 dní',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Zmeny podľa domény za posledných 7 dní',
|
||||
|
||||
@@ -20,13 +20,13 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'Menu:SearchChanges' => 'Değişiklik ara',
|
||||
'Menu:SearchChanges+' => 'Değişiklik isteği ara',
|
||||
'Menu:Change:Shortcuts' => 'Kısayollar',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Kabul bekleyen değişiklik talepleri',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Onay bekleyen değişiklik talepleri',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Açık değişiklikler',
|
||||
'Menu:Changes+' => '',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => 'Bana atanan değişiklik istekleri',
|
||||
'Menu:MyChanges+' => 'Bana atanan değişiklik istekleri',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Son 7 gün için kategoriye göre değişiklikler',
|
||||
|
||||
@@ -31,11 +31,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Menu:SearchChanges' => '搜索变更',
|
||||
'Menu:SearchChanges+' => '搜索变更',
|
||||
'Menu:Change:Shortcuts' => '快捷方式',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => '等待审核的变更',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => '等待批准的变更',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => '所有打开的变更',
|
||||
'Menu:Changes+' => '所有打开的变更',
|
||||
'Menu:MyChanges' => '分配给我的变更',
|
||||
|
||||
@@ -21,11 +21,11 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Menu:SearchChanges' => 'Hledat změny',
|
||||
'Menu:SearchChanges+' => 'Hledat změnové tikety',
|
||||
'Menu:Change:Shortcuts' => 'Odkazy',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Změny čekající na přijetí',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Změny čekající na schválení',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Otevřené změny',
|
||||
'Menu:Changes+' => 'Všechny otevřené změny',
|
||||
'Menu:MyChanges' => 'Změny přidělené mně',
|
||||
|
||||
@@ -20,13 +20,13 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Menu:SearchChanges' => 'Søg efter Changes',
|
||||
'Menu:SearchChanges+' => '',
|
||||
'Menu:Change:Shortcuts' => 'Genveje',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes der afventer accept',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes der afventer godkendelse',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Åbne Changes',
|
||||
'Menu:Changes+' => '',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => 'Changes tildelt til mig',
|
||||
'Menu:MyChanges+' => '',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changes de sidste 7 dage efter kategori',
|
||||
|
||||
@@ -19,8 +19,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Menu:NewChange+' => 'Einen neuen Change erstellen',
|
||||
'Menu:SearchChanges' => 'Suche nach Changes',
|
||||
'Menu:SearchChanges+' => 'Unter den bestehenden Changes suchen',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts' => 'Changes~~',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes, die auf Annahme warten',
|
||||
'Menu:WaitingAcceptance+' => 'Changes, die auf Annahme warten',
|
||||
'Menu:WaitingApproval' => 'Changes, die auf Genehmigung warten',
|
||||
|
||||
@@ -30,16 +30,16 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Menu:NewChange+' => 'Create a new change ticket',
|
||||
'Menu:SearchChanges' => 'Search for changes',
|
||||
'Menu:SearchChanges+' => 'Search for change tickets',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Changes awaiting acceptance',
|
||||
'Menu:Change:Shortcuts' => 'Changes',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes',
|
||||
'Menu:WaitingAcceptance' => 'Awaiting acceptance',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes awaiting approval',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:Changes' => 'Open changes',
|
||||
'Menu:Changes+' => 'All open changes',
|
||||
'Menu:MyChanges' => 'Changes assigned to me',
|
||||
'Menu:MyChanges+' => 'Changes assigned to me (as Agent)',
|
||||
'Menu:WaitingApproval' => 'Awaiting approval',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status',
|
||||
'Menu:Changes' => 'Open',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status',
|
||||
'Menu:MyChanges' => 'Assigned to me',
|
||||
'Menu:MyChanges+' => 'Non-closed changes assigned to me (as an Agent)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changes by category for the last 7 days',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Number of changes for the last 7 days',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days',
|
||||
|
||||
@@ -30,16 +30,16 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Menu:NewChange+' => 'Create a new change ticket',
|
||||
'Menu:SearchChanges' => 'Search for changes',
|
||||
'Menu:SearchChanges+' => 'Search for change tickets',
|
||||
'Menu:Change:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts' => 'Changes~~',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes awaiting acceptance',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes awaiting approval',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Open changes',
|
||||
'Menu:Changes+' => 'All open changes',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status',
|
||||
'Menu:MyChanges' => 'Changes assigned to me',
|
||||
'Menu:MyChanges+' => 'Changes assigned to me (as Agent)',
|
||||
'Menu:MyChanges+' => 'Non-closed changes assigned to me (as an Agent)',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changes by category for the last 7 days',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Number of changes for the last 7 days',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changes by domain for the last 7 days',
|
||||
|
||||
@@ -18,16 +18,16 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Menu:NewChange+' => 'Créer un nouveau ticket de changement',
|
||||
'Menu:SearchChanges' => 'Rechercher des changements',
|
||||
'Menu:SearchChanges+' => 'Rechercher parmi les tickets de changement',
|
||||
'Menu:Change:Shortcuts' => 'Raccourcis',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:WaitingAcceptance' => 'Changements en attente d\'acceptance',
|
||||
'Menu:WaitingAcceptance+' => 'Changements en attente d\'acceptance',
|
||||
'Menu:WaitingApproval' => 'Changement en attente d\'approbation',
|
||||
'Menu:WaitingApproval+' => 'Changement en attente d\'approbation',
|
||||
'Menu:Changes' => 'Changements ouverts',
|
||||
'Menu:Changes+' => 'Tickets de changement ouverts',
|
||||
'Menu:MyChanges' => 'Mes tickets de changement',
|
||||
'Menu:MyChanges+' => 'Tickets de changement qui me sont assignés',
|
||||
'Menu:Change:Shortcuts' => 'Changements',
|
||||
'Menu:Change:Shortcuts+' => 'Raccourcis vers différents groupes de changements',
|
||||
'Menu:WaitingAcceptance' => 'En attente d\'acceptation',
|
||||
'Menu:WaitingAcceptance+' => 'Changements en attente d\'acceptation',
|
||||
'Menu:WaitingApproval' => 'En attente d\'approbation',
|
||||
'Menu:WaitingApproval+' => 'Changements dans l\'état planifié',
|
||||
'Menu:Changes' => 'En cours',
|
||||
'Menu:Changes+' => 'Tickets de changement qui ne sont pas dans l\'état fermé',
|
||||
'Menu:MyChanges' => 'Qui me sont assignés',
|
||||
'Menu:MyChanges+' => 'Changements non fermés dont je suis l\'agent assigné',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Changements par catégorie',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Changements par jour',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Changements par domaine',
|
||||
|
||||
@@ -23,7 +23,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Menu:WaitingAcceptance' => 'Modifiche in attesa di accettazione',
|
||||
'Menu:WaitingAcceptance+' => '~~',
|
||||
'Menu:WaitingApproval' => 'Modifiche in attesa di approvazione',
|
||||
'Menu:WaitingApproval+' => '~~',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Modifiche aperte',
|
||||
'Menu:Changes+' => 'Tutte le Modifiche aperte',
|
||||
'Menu:MyChanges' => 'Modifiche assegnate a me',
|
||||
|
||||
@@ -19,13 +19,13 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'Menu:SearchChanges' => '変更検索',
|
||||
'Menu:SearchChanges+' => '',
|
||||
'Menu:Change:Shortcuts' => 'ショートカット',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => '受け付け待ちの変更',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => '承認待ちの変更',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'オープンな変更',
|
||||
'Menu:Changes+' => '',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => '私に割り当てられた変更',
|
||||
'Menu:MyChanges+' => '',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => '最近7日間のカテゴリ別の変更',
|
||||
|
||||
@@ -21,11 +21,11 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'Menu:SearchChanges' => 'Zoek naar changes',
|
||||
'Menu:SearchChanges+' => 'Zoek naar changes',
|
||||
'Menu:Change:Shortcuts' => 'Snelkoppelingen',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Changes die acceptatie vereisen',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Changes die goedkeuring vereisen',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Open changes',
|
||||
'Menu:Changes+' => 'Alle open changes',
|
||||
'Menu:MyChanges' => 'Changes toegewezen aan mij',
|
||||
|
||||
@@ -19,11 +19,11 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'Menu:SearchChanges' => 'Szukaj zmian',
|
||||
'Menu:SearchChanges+' => 'Szukaj zgłoszeń zmian',
|
||||
'Menu:Change:Shortcuts' => 'Skróty',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Zmiany do akceptacji',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Zmiany do zatwierdzenia',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Otwarte zmiany',
|
||||
'Menu:Changes+' => 'Wszystkie otwarte zmiany',
|
||||
'Menu:MyChanges' => 'Zmiany przypisane do mnie',
|
||||
|
||||
@@ -19,11 +19,11 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'Menu:SearchChanges' => 'Pesquisar por mudanças',
|
||||
'Menu:SearchChanges+' => 'Pesquisar por solicitações de mudanças',
|
||||
'Menu:Change:Shortcuts' => 'Atalhos',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => 'Mudanças aguardando aceitação',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => 'Mudanças aguardando aprovação',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Mudanças abertas',
|
||||
'Menu:Changes+' => 'Todas as mudanças abertas',
|
||||
'Menu:MyChanges' => 'Mudanças atribuídas a mim',
|
||||
|
||||
@@ -23,11 +23,11 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Menu:WaitingAcceptance' => 'Zmeny očakávajúce prijatie',
|
||||
'Menu:WaitingAcceptance+' => '~~',
|
||||
'Menu:WaitingApproval' => 'Zmeny očakávajúce schválenie',
|
||||
'Menu:WaitingApproval+' => '~~',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Otvorené zmeny',
|
||||
'Menu:Changes+' => 'All open changes~~',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => 'Zmeny pridelené mne',
|
||||
'Menu:MyChanges+' => 'Changes assigned to me (as Agent)~~',
|
||||
'Menu:MyChanges+' => 'Non-closed changes assigned to me (as an Agent)~~',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Zmeny podľa kategórie za posledných 7 dní',
|
||||
'UI-ChangeManagementOverview-Last-7-days' => 'Počet zmien za posledných 7 dní',
|
||||
'UI-ChangeManagementOverview-ChangeByDomain-last-7-days' => 'Zmeny podľa domény za posledných 7 dní',
|
||||
|
||||
@@ -23,9 +23,9 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'Menu:WaitingAcceptance' => 'Kabul bekleyen değişiklik talepleri',
|
||||
'Menu:WaitingAcceptance+' => '~~',
|
||||
'Menu:WaitingApproval' => 'Onay bekleyen değişiklik talepleri',
|
||||
'Menu:WaitingApproval+' => '~~',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => 'Açık değişiklikler',
|
||||
'Menu:Changes+' => 'All open changes~~',
|
||||
'Menu:Changes+' => 'All changes which are not in closed status~~',
|
||||
'Menu:MyChanges' => 'Bana atanan değişiklik istekleri',
|
||||
'Menu:MyChanges+' => 'Bana atanan değişiklik istekleri',
|
||||
'UI-ChangeManagementOverview-ChangeByCategory-last-7-days' => 'Son 7 gün için kategoriye göre değişiklikler',
|
||||
|
||||
@@ -30,11 +30,11 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Menu:SearchChanges' => '搜索变更',
|
||||
'Menu:SearchChanges+' => '搜索变更',
|
||||
'Menu:Change:Shortcuts' => '快捷方式',
|
||||
'Menu:Change:Shortcuts+' => '',
|
||||
'Menu:Change:Shortcuts+' => 'Shortcuts to predefined sets of Changes~~',
|
||||
'Menu:WaitingAcceptance' => '等待审核的变更',
|
||||
'Menu:WaitingAcceptance+' => '',
|
||||
'Menu:WaitingApproval' => '等待批准的变更',
|
||||
'Menu:WaitingApproval+' => '',
|
||||
'Menu:WaitingApproval+' => 'Changes in planned status~~',
|
||||
'Menu:Changes' => '所有打开的变更',
|
||||
'Menu:Changes+' => '所有打开的变更',
|
||||
'Menu:MyChanges' => '分配给我的变更',
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -242,8 +242,7 @@ class AjaxController extends Controller
|
||||
throw new SecurityException('Access forbidden');
|
||||
}
|
||||
|
||||
$sConfigFile = APPCONF.'production/config-itop.php';
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
SetupUtils::CreateSetupToken();
|
||||
|
||||
header('Location: ../setup/');
|
||||
}
|
||||
|
||||
@@ -166,8 +166,6 @@ class UpdateController extends Controller
|
||||
public function OperationRunSetup()
|
||||
{
|
||||
SetupUtils::CheckSetupToken(true);
|
||||
$sConfigFile = APPCONF.'production/'.ITOP_CONFIG_FILE;
|
||||
@chmod($sConfigFile, 0770);
|
||||
$sRedirectURL = utils::GetAbsoluteUrlAppRoot().'setup/index.php';
|
||||
header("Location: $sRedirectURL");
|
||||
}
|
||||
|
||||
@@ -46,10 +46,10 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
]);
|
||||
Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Menu:ProblemManagement' => 'Správa problémů',
|
||||
'Menu:ProblemManagement+' => 'Správa problémů',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Odkazy',
|
||||
'Menu:FAQCategory' => 'Kategorie FAQ',
|
||||
'Menu:FAQCategory+' => '',
|
||||
'Menu:FAQCategory+' => 'A typology to categorize frequently asked questions (FAQ)~~',
|
||||
'Menu:FAQ' => 'FAQ',
|
||||
'Menu:FAQ+' => 'FAQ - Často kladené dotazy',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
|
||||
@@ -45,10 +45,10 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
]);
|
||||
Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Menu:ProblemManagement' => 'Problem Management',
|
||||
'Menu:ProblemManagement+' => 'Problem Management',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Genvej',
|
||||
'Menu:FAQCategory' => 'FAQ-Kategorier',
|
||||
'Menu:FAQCategory+' => '',
|
||||
'Menu:FAQCategory+' => 'A typology to categorize frequently asked questions (FAQ)~~',
|
||||
'Menu:FAQ' => 'FAQs',
|
||||
'Menu:FAQ+' => '',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ~~',
|
||||
|
||||
@@ -45,10 +45,10 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
]);
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Menu:ProblemManagement' => 'Problem Management',
|
||||
'Menu:ProblemManagement+' => 'Problem Management',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Shortcuts',
|
||||
'Menu:FAQCategory' => 'FAQ-Kategorien',
|
||||
'Menu:FAQCategory+' => '',
|
||||
'Menu:FAQCategory+' => 'A typology to categorize frequently asked questions (FAQ)~~',
|
||||
'Menu:FAQ' => 'FAQs',
|
||||
'Menu:FAQ+' => '',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
|
||||
@@ -85,12 +85,12 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
]);
|
||||
Dict::Add('EN US', 'English', 'English', [
|
||||
'Menu:ProblemManagement' => 'Problem management',
|
||||
'Menu:ProblemManagement+' => 'Problem management',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload',
|
||||
'Menu:Problem:Shortcuts' => 'Shortcuts',
|
||||
'Menu:FAQCategory' => 'FAQ categories',
|
||||
'Menu:FAQCategory+' => 'All FAQ categories',
|
||||
'Menu:FAQCategory+' => 'A typology to categorize frequently asked questions (FAQ)',
|
||||
'Menu:FAQ' => 'FAQs',
|
||||
'Menu:FAQ+' => 'All FAQs',
|
||||
'Menu:FAQ+' => 'All Frequently Asked Questions',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
'Brick:Portal:FAQ:Title' => 'Frequently Asked Questions',
|
||||
'Brick:Portal:FAQ:Title+' => '<p>In a hurry?</p><p>Check out the list of most common questions and (maybe) find the expected answer right away.</p>',
|
||||
|
||||
@@ -85,12 +85,12 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
]);
|
||||
Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Menu:ProblemManagement' => 'Problem management',
|
||||
'Menu:ProblemManagement+' => 'Problem management',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Shortcuts',
|
||||
'Menu:FAQCategory' => 'FAQ categories',
|
||||
'Menu:FAQCategory+' => 'All FAQ categories',
|
||||
'Menu:FAQCategory+' => 'A typology to categorize frequently asked questions (FAQ)',
|
||||
'Menu:FAQ' => 'FAQs',
|
||||
'Menu:FAQ+' => 'All FAQs',
|
||||
'Menu:FAQ+' => 'All Frequently Asked Questions',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ',
|
||||
'Brick:Portal:FAQ:Title' => 'Frequently Asked Questions',
|
||||
'Brick:Portal:FAQ:Title+' => '<p>In a hurry?</p><p>Check out the list of most common questions and (maybe) find the expected answer right away.</p>',
|
||||
|
||||
@@ -42,7 +42,7 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
]);
|
||||
Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'Menu:ProblemManagement' => 'Administración de Problemas',
|
||||
'Menu:ProblemManagement+' => 'GestAdministraciónión de problemas',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Acceso Rápido',
|
||||
'Menu:FAQCategory' => 'Categorías de FAQ',
|
||||
'Menu:FAQCategory+' => 'Categorías FAQ',
|
||||
|
||||
@@ -36,7 +36,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:FAQCategory' => 'Catégorie de FAQ',
|
||||
'Class:FAQCategory+' => 'Typologie. Segmentation des Questions fréquement posées (FAQ)',
|
||||
'Class:FAQCategory+' => 'Segmentation de la Foire Aux Questions (FAQ)',
|
||||
'Class:FAQCategory/Attribute:name' => 'Nom',
|
||||
'Class:FAQCategory/Attribute:name+' => '',
|
||||
'Class:FAQCategory/Attribute:faq_list' => 'FAQs',
|
||||
@@ -50,7 +50,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
]);
|
||||
Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Menu:ProblemManagement' => 'Gestion des problèmes',
|
||||
'Menu:ProblemManagement+' => 'Gestion des problèmes',
|
||||
'Menu:ProblemManagement+' => 'Un processus ITIL qui identifie la cause des incidents répétitifs, documente les Erreurs connues et les FAQs, afin de réduire la charge de travail du heldesk',
|
||||
'Menu:Problem:Shortcuts' => 'Raccourcis',
|
||||
'Menu:FAQCategory' => 'Catégories de FAQ',
|
||||
'Menu:FAQCategory+' => 'Toutes les catégories de FAQ',
|
||||
|
||||
@@ -44,7 +44,7 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
]);
|
||||
Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'Menu:ProblemManagement' => 'Problémakezelés',
|
||||
'Menu:ProblemManagement+' => '',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Gyorsgombok',
|
||||
'Menu:FAQCategory' => 'Tudástár kategória',
|
||||
'Menu:FAQCategory+' => 'Tudástár kategóriák',
|
||||
|
||||
@@ -44,7 +44,7 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
]);
|
||||
Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Menu:ProblemManagement' => 'Gestione dei problemi',
|
||||
'Menu:ProblemManagement+' => 'Gestione dei problemi',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Scorciatoia',
|
||||
'Menu:FAQCategory' => 'Categoria FAQ',
|
||||
'Menu:FAQCategory+' => 'Tutte le categorie FAQ',
|
||||
|
||||
@@ -44,7 +44,7 @@ Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
]);
|
||||
Dict::Add('JA JP', 'Japanese', '日本語', [
|
||||
'Menu:ProblemManagement' => '問題管理',
|
||||
'Menu:ProblemManagement+' => '問題管理',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'ショートカット',
|
||||
'Menu:FAQCategory' => 'FAQカテゴリ',
|
||||
'Menu:FAQCategory+' => '全てのFAQカテゴリ',
|
||||
|
||||
@@ -46,7 +46,7 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
]);
|
||||
Dict::Add('NL NL', 'Dutch', 'Nederlands', [
|
||||
'Menu:ProblemManagement' => 'Probleem Management',
|
||||
'Menu:ProblemManagement+' => 'Probleem Management',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Snelkoppelingen',
|
||||
'Menu:FAQCategory' => 'FAQ-categorieën',
|
||||
'Menu:FAQCategory+' => 'Alle FAQ-categorieën',
|
||||
|
||||
@@ -44,7 +44,7 @@ Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
]);
|
||||
Dict::Add('PL PL', 'Polish', 'Polski', [
|
||||
'Menu:ProblemManagement' => 'Zarządzanie problemami',
|
||||
'Menu:ProblemManagement+' => 'Zarządzanie problemami',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Skróty',
|
||||
'Menu:FAQCategory' => 'Kategorie pytań FAQ',
|
||||
'Menu:FAQCategory+' => 'Wszystkie kategorie pytań FAQ',
|
||||
|
||||
@@ -44,7 +44,7 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
]);
|
||||
Dict::Add('PT BR', 'Brazilian', 'Brazilian', [
|
||||
'Menu:ProblemManagement' => 'Gerencimento de problemas',
|
||||
'Menu:ProblemManagement+' => '',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Atalhos',
|
||||
'Menu:FAQCategory' => 'Categorias de FAQ',
|
||||
'Menu:FAQCategory+' => 'Lista de Categorias de FAQ',
|
||||
|
||||
@@ -45,7 +45,7 @@ Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
]);
|
||||
Dict::Add('RU RU', 'Russian', 'Русский', [
|
||||
'Menu:ProblemManagement' => 'Управление проблемами',
|
||||
'Menu:ProblemManagement+' => 'Управление проблемами',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Ярлыки',
|
||||
'Menu:FAQCategory' => 'Категории FAQ',
|
||||
'Menu:FAQCategory+' => 'Категории FAQ',
|
||||
|
||||
@@ -44,12 +44,12 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
]);
|
||||
Dict::Add('SK SK', 'Slovak', 'Slovenčina', [
|
||||
'Menu:ProblemManagement' => 'Problem management~~',
|
||||
'Menu:ProblemManagement+' => 'Problem management~~',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Shortcuts~~',
|
||||
'Menu:FAQCategory' => 'FAQ categories~~',
|
||||
'Menu:FAQCategory+' => 'All FAQ categories~~',
|
||||
'Menu:FAQCategory+' => 'A typology to categorize frequently asked questions (FAQ)~~',
|
||||
'Menu:FAQ' => 'FAQs~~',
|
||||
'Menu:FAQ+' => 'All FAQs~~',
|
||||
'Menu:FAQ+' => 'All Frequently Asked Questions~~',
|
||||
'Brick:Portal:FAQ:Menu' => 'FAQ~~',
|
||||
'Brick:Portal:FAQ:Title' => 'Frequently Asked Questions~~',
|
||||
'Brick:Portal:FAQ:Title+' => '<p>In a hurry?</p><p>Check out the list of most common questions and (maybe) find the expected answer right away.</p>~~',
|
||||
|
||||
@@ -45,7 +45,7 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
]);
|
||||
Dict::Add('TR TR', 'Turkish', 'Türkçe', [
|
||||
'Menu:ProblemManagement' => 'Problem yönetimi',
|
||||
'Menu:ProblemManagement+' => 'Problem yönetimi',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => 'Kısayollar',
|
||||
'Menu:FAQCategory' => 'SSS kategorileri',
|
||||
'Menu:FAQCategory+' => 'Tüm SSS kategorileri',
|
||||
|
||||
@@ -85,7 +85,7 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
]);
|
||||
Dict::Add('ZH CN', 'Chinese', '简体中文', [
|
||||
'Menu:ProblemManagement' => '问题管理',
|
||||
'Menu:ProblemManagement+' => '问题管理',
|
||||
'Menu:ProblemManagement+' => 'An ITIL process that identifies root causes of incidents, documents Known Errors and FAQs, in order to reduce helpdesk workload~~',
|
||||
'Menu:Problem:Shortcuts' => '快捷方式',
|
||||
'Menu:FAQCategory' => 'FAQ 类别',
|
||||
'Menu:FAQCategory+' => '所有 FAQ 类别',
|
||||
|
||||
@@ -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));
|
||||
|
||||
@@ -133,8 +133,7 @@ class HubController
|
||||
throw new Exception('Sorry the installation of extensions is not allowed in demo mode');
|
||||
}
|
||||
|
||||
$aSelectModules = $oRuntimeEnv->CompileFrom('production'); // WARNING symlinks does not seem to be compatible with manual Commit
|
||||
|
||||
$oRuntimeEnv->CompileFrom('production'); // WARNING symlinks does not seem to be compatible with manual Commit
|
||||
$oRuntimeEnv->UpdateIncludes($oConfig);
|
||||
|
||||
$oRuntimeEnv->InitDataModel($oConfig, true /* model only */);
|
||||
|
||||
@@ -1767,6 +1767,13 @@
|
||||
<do_search>1</do_search>
|
||||
<auto_reload>fast</auto_reload>
|
||||
</menu>
|
||||
<menu id="Incident:MySupportIncidents" xsi:type="OQLMenuNode" _delta="define">
|
||||
<rank>3</rank>
|
||||
<parent>Incident:Shortcuts</parent>
|
||||
<oql><![CDATA[SELECT Incident WHERE caller_id = :current_contact_id AND status NOT IN ("closed")]]></oql>
|
||||
<do_search/>
|
||||
<auto_reload>fast</auto_reload>
|
||||
</menu>
|
||||
</menus>
|
||||
<user_rights>
|
||||
<profiles>
|
||||
|
||||
@@ -25,6 +25,8 @@ Dict::Add('CS CZ', 'Czech', 'Čeština', [
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Incidenty přidělené mně',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidenty přidělené mně (jako řešiteli)',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Eskalované incidenty',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Eskalované incidenty',
|
||||
'Menu:Incident:OpenIncidents' => 'Všechny otevřené incidenty',
|
||||
|
||||
@@ -24,10 +24,12 @@ Dict::Add('DA DA', 'Danish', 'Dansk', [
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Mine Incidents',
|
||||
'Menu:Incident:MyIncidents+' => '',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Eskalerede Incidents',
|
||||
'Menu:Incident:EscalatedIncidents+' => '',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Incident which are under escalation, by status or hot flag~~',
|
||||
'Menu:Incident:OpenIncidents' => 'Alle åbne Incidents',
|
||||
'Menu:Incident:OpenIncidents+' => '',
|
||||
'Menu:Incident:OpenIncidents+' => 'All incidents that are not closed~~',
|
||||
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => 'Incidents de sidste 14 dage efter prioritet',
|
||||
'UI-IncidentManagementOverview-Last-14-days' => 'Antal Incidents de sidste 14 dage',
|
||||
'UI-IncidentManagementOverview-OpenIncidentByStatus' => 'Åbne Incidents efter status',
|
||||
|
||||
@@ -20,10 +20,12 @@ Dict::Add('DE DE', 'German', 'Deutsch', [
|
||||
'Menu:NewIncident+' => 'Einen neuen Incident dokumentieren',
|
||||
'Menu:SearchIncidents' => 'Nach Incidents suchen',
|
||||
'Menu:SearchIncidents+' => 'Suche nach einem bestehendem Incident',
|
||||
'Menu:Incident:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Incident:Shortcuts' => 'Incidents',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Mir zugewiesene Incidents',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidents die mir als Bearbeiter zugewiesen sind',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Eskalierte Incidents',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Incidents die eskaliert sind',
|
||||
'Menu:Incident:OpenIncidents' => 'Alle offenen Incidents',
|
||||
|
||||
@@ -31,14 +31,16 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Menu:NewIncident+' => 'Create a new incident ticket',
|
||||
'Menu:SearchIncidents' => 'Search for incidents',
|
||||
'Menu:SearchIncidents+' => 'Search for incident tickets',
|
||||
'Menu:Incident:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Incident:Shortcuts' => 'Incidents',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Incidents assigned to me',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidents assigned to me (as Agent)',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Escalated incidents',
|
||||
'Menu:Incident:EscalatedIncidents+' => '',
|
||||
'Menu:Incident:OpenIncidents' => 'All open incidents',
|
||||
'Menu:Incident:OpenIncidents+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Assigned to me',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidents assigned to me (as an Agent)',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Under escalation',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Incident which are under escalation, by status or hot flag',
|
||||
'Menu:Incident:OpenIncidents' => 'Open',
|
||||
'Menu:Incident:OpenIncidents+' => 'All incidents that are not closed',
|
||||
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => 'Last 14 days incident per priority',
|
||||
'UI-IncidentManagementOverview-Last-14-days' => 'Last 14 days number of incidents',
|
||||
'UI-IncidentManagementOverview-OpenIncidentByStatus' => 'Open incidents by status',
|
||||
@@ -134,7 +136,7 @@ Dict::Add('EN US', 'English', 'English', [
|
||||
'Class:Incident/Attribute:servicesubcategory_name' => 'Service subcategory name',
|
||||
'Class:Incident/Attribute:servicesubcategory_name+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag' => 'Hot Flag',
|
||||
'Class:Incident/Attribute:escalation_flag+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag+' => 'When set, the Ticket is added to the "Under escalation" menu',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:no' => 'No',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:no+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:yes' => 'Yes',
|
||||
|
||||
@@ -31,14 +31,16 @@ Dict::Add('EN GB', 'British English', 'British English', [
|
||||
'Menu:NewIncident+' => 'Create a new incident ticket',
|
||||
'Menu:SearchIncidents' => 'Search for incidents',
|
||||
'Menu:SearchIncidents+' => 'Search for incident tickets',
|
||||
'Menu:Incident:Shortcuts' => 'Shortcuts',
|
||||
'Menu:Incident:Shortcuts' => 'Incidents',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Incidents assigned to me',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidents assigned to me (as Agent)',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Escalated incidents',
|
||||
'Menu:Incident:EscalatedIncidents+' => '',
|
||||
'Menu:Incident:OpenIncidents' => 'All open incidents',
|
||||
'Menu:Incident:OpenIncidents+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Assigned to me',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidents assigned to me (as an Agent)',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Under escalation',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Incident which are under escalation, by status or hot flag',
|
||||
'Menu:Incident:OpenIncidents' => 'Open',
|
||||
'Menu:Incident:OpenIncidents+' => 'All incidents that are not closed~~',
|
||||
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => 'Last 14 days incident per priority',
|
||||
'UI-IncidentManagementOverview-Last-14-days' => 'Last 14 days number of incidents',
|
||||
'UI-IncidentManagementOverview-OpenIncidentByStatus' => 'Open incidents by status',
|
||||
|
||||
@@ -21,6 +21,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', [
|
||||
'Menu:Incident:Shortcuts+' => 'Accesos Rápidos',
|
||||
'Menu:Incident:MyIncidents' => 'Incidentes Asignados a Mí',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidentes Asignados a Mí (como Analista)',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Incidentes Escalados',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Incidentes Escalados',
|
||||
'Menu:Incident:OpenIncidents' => 'Incidentes Abiertos',
|
||||
|
||||
@@ -19,13 +19,15 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Menu:NewIncident+' => 'Créer un nouveau ticket d\'incident',
|
||||
'Menu:SearchIncidents' => 'Rechercher des incidents',
|
||||
'Menu:SearchIncidents+' => 'Rechercher parmi les tickets d\'incidents',
|
||||
'Menu:Incident:Shortcuts' => 'Raccourcis',
|
||||
'Menu:Incident:Shortcuts' => 'Incidents',
|
||||
'Menu:Incident:Shortcuts+' => '',
|
||||
'Menu:Incident:MyIncidents' => 'Mes incidents',
|
||||
'Menu:Incident:MyIncidents+' => 'Tickets d\'incident qui me sont assignés',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Incidents en cours d\'escalade',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Ticket d\'incident en cours d\'escalade',
|
||||
'Menu:Incident:OpenIncidents' => 'Incidents ouverts',
|
||||
'Menu:Incident:MyIncidents' => 'Qui me sont assignés',
|
||||
'Menu:Incident:MyIncidents+' => 'Les tickets d\'incident en cours qui me sont assignés',
|
||||
'Menu:Incident:MySupportIncidents' => 'Que j\'ai déclarés',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Les incidents en cours dont je suis le demandeur',
|
||||
'Menu:Incident:EscalatedIncidents' => 'En escalade',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Ticket d\'incident en cours d\'escalade ou à surveiller',
|
||||
'Menu:Incident:OpenIncidents' => 'En cours',
|
||||
'Menu:Incident:OpenIncidents+' => 'Tous les tickets d\'incident ouverts',
|
||||
'UI-IncidentManagementOverview-IncidentByPriority-last-14-days' => 'Incidents des 14 derniers jours par priorité',
|
||||
'UI-IncidentManagementOverview-Last-14-days' => 'Incidents des 14 derniers jours',
|
||||
@@ -120,7 +122,7 @@ Dict::Add('FR FR', 'French', 'Français', [
|
||||
'Class:Incident/Attribute:servicesubcategory_name' => 'Nom Sous-catégorie de service',
|
||||
'Class:Incident/Attribute:servicesubcategory_name+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag' => 'Ticket à surveiller',
|
||||
'Class:Incident/Attribute:escalation_flag+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag+' => 'Ce Ticket sera ajouté au menu des incidents en cours d\'escalade',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:no' => 'Non',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:no+' => '',
|
||||
'Class:Incident/Attribute:escalation_flag/Value:yes' => 'Oui',
|
||||
|
||||
@@ -23,6 +23,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', [
|
||||
'Menu:Incident:Shortcuts+' => 'Gyorselérés gombok',
|
||||
'Menu:Incident:MyIncidents' => 'Hozzám rendelt incidensek',
|
||||
'Menu:Incident:MyIncidents+' => 'Hozzám rendelt incidensek (ügyintézőként)',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Eszkalált incidensek',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Eszkalált incidensek',
|
||||
'Menu:Incident:OpenIncidents' => 'Nyitott incidensek',
|
||||
|
||||
@@ -23,6 +23,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', [
|
||||
'Menu:Incident:Shortcuts+' => '~~',
|
||||
'Menu:Incident:MyIncidents' => 'Incidenti assegnati a me',
|
||||
'Menu:Incident:MyIncidents+' => 'Incidenti assegnati a me (come agente)',
|
||||
'Menu:Incident:MySupportIncidents' => 'Reported by me~~',
|
||||
'Menu:Incident:MySupportIncidents+' => 'Non closed incidents where I am the caller~~',
|
||||
'Menu:Incident:EscalatedIncidents' => 'Evoluzione Incidente',
|
||||
'Menu:Incident:EscalatedIncidents+' => 'Evoluzione Incidente',
|
||||
'Menu:Incident:OpenIncidents' => 'Tutti gli incidenti aperti',
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user