mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-16 00:44:10 +01:00
Compare commits
153 Commits
feature/fa
...
feature/51
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
05b69208a8 | ||
|
|
c0f0e354dd | ||
|
|
d6f58d04f1 | ||
|
|
cc88ee1de0 | ||
|
|
8008e4d840 | ||
|
|
a4390fbb57 | ||
|
|
f4170ade8a | ||
|
|
e81587470d | ||
|
|
fc6df1063c | ||
|
|
5a37bc338a | ||
|
|
f4a027b474 | ||
|
|
d0ba0d193b | ||
|
|
1d9a9bcb28 | ||
|
|
178ba60973 | ||
|
|
8e6e2432d3 | ||
|
|
83ec19dfca | ||
|
|
6e619f2c35 | ||
|
|
163ba41e8d | ||
|
|
ec143c43db | ||
|
|
cacf0004a5 | ||
|
|
cb39541e2a | ||
|
|
b9ddadeb44 | ||
|
|
dabd2a3f4d | ||
|
|
11e811cc4b | ||
|
|
c47f224566 | ||
|
|
8fcd454445 | ||
|
|
e422adb0d0 | ||
|
|
b03e28efb9 | ||
|
|
7b3d859522 | ||
|
|
ba9d5f0c4b | ||
|
|
e02d9f3f0e | ||
|
|
e831d66b76 | ||
|
|
0efc978004 | ||
|
|
6fa2d47780 | ||
|
|
e691454339 | ||
|
|
079b406f18 | ||
|
|
dbe02a42c2 | ||
|
|
b026e5ab87 | ||
|
|
1e75154cc7 | ||
|
|
94365ea40e | ||
|
|
e4a04de9f4 | ||
|
|
645e612e8b | ||
|
|
26a78a10bc | ||
|
|
1feb5e6ad6 | ||
|
|
2716f9d24c | ||
|
|
bac2918ceb | ||
|
|
92997e3e57 | ||
|
|
604837c770 | ||
|
|
f32c283c9c | ||
|
|
27d06a712b | ||
|
|
b15050487c | ||
|
|
46f232d561 | ||
|
|
63976df2e1 | ||
|
|
42599eae64 | ||
|
|
3514e21772 | ||
|
|
3463b1715a | ||
|
|
b75f29b8d7 | ||
|
|
81d285a143 | ||
|
|
631b38a160 | ||
|
|
0287500feb | ||
|
|
e4cbaf7096 | ||
|
|
ad4442ae78 | ||
|
|
73c6b4be20 | ||
|
|
fde2103659 | ||
|
|
24500216f6 | ||
|
|
2039b872d3 | ||
|
|
b368c593e5 | ||
|
|
c9c731a2a5 | ||
|
|
8204723b5b | ||
|
|
f93218a80f | ||
|
|
4f5a9c898c | ||
|
|
7ce5712b71 | ||
|
|
90b41e0b81 | ||
|
|
9d2c89f118 | ||
|
|
61137a6f65 | ||
|
|
a26c8fbd48 | ||
|
|
0080a2e733 | ||
|
|
992ee3a74b | ||
|
|
e45013891c | ||
|
|
1db4b9a12e | ||
|
|
ea043960ff | ||
|
|
d0f83046cd | ||
|
|
7f4fddb378 | ||
|
|
9cd076131f | ||
|
|
a71cb97db3 | ||
|
|
0c80a4e430 | ||
|
|
779211e638 | ||
|
|
4c99f497cc | ||
|
|
d1e2be97d2 | ||
|
|
93c6cfffda | ||
|
|
b50ba0ad49 | ||
|
|
0205cdf713 | ||
|
|
39fc59a8b2 | ||
|
|
107c9adf60 | ||
|
|
143c30b099 | ||
|
|
d29880b1b8 | ||
|
|
3edfc2016d | ||
|
|
5f80be75ed | ||
|
|
0d4796ae2b | ||
|
|
2d156bd77b | ||
|
|
5908ec5197 | ||
|
|
d122dbfdd6 | ||
|
|
46d58e6512 | ||
|
|
6cf781da33 | ||
|
|
0f2cbaf186 | ||
|
|
7ddb47dc83 | ||
|
|
f4ecdf116a | ||
|
|
304e379c01 | ||
|
|
93a138606f | ||
|
|
70074ee1cb | ||
|
|
d28ccb264f | ||
|
|
8d4545f008 | ||
|
|
9f95d45f51 | ||
|
|
8ab38854a8 | ||
|
|
bceb570d84 | ||
|
|
138fa569f2 | ||
|
|
5854c199d0 | ||
|
|
a937d08655 | ||
|
|
4bdf84bf6c | ||
|
|
9ce88699ca | ||
|
|
f9e8bf88c8 | ||
|
|
bddf7a11c8 | ||
|
|
ee7fb15fc2 | ||
|
|
8473df0f0c | ||
|
|
7eab003f3c | ||
|
|
d437e2d662 | ||
|
|
60c372f535 | ||
|
|
22f9d16743 | ||
|
|
3d3d94e837 | ||
|
|
3bec96abe1 | ||
|
|
44c18395b3 | ||
|
|
09ff052c1f | ||
|
|
9ef5fd70c0 | ||
|
|
3b599a40f3 | ||
|
|
1495ab992f | ||
|
|
d89dc1aa4d | ||
|
|
1fac2ae787 | ||
|
|
ff7d1f2d6a | ||
|
|
91d4da85e1 | ||
|
|
dcd52d6919 | ||
|
|
9a75ca2c21 | ||
|
|
812606db78 | ||
|
|
c17ceb1702 | ||
|
|
ce01dad875 | ||
|
|
9ca106d889 | ||
|
|
5f575d524a | ||
|
|
16142bd979 | ||
|
|
c1e2ba8abc | ||
|
|
cc2efe432e | ||
|
|
e879ae2f11 | ||
|
|
8bcd2ce571 | ||
|
|
d301562ffe | ||
|
|
caed22ea8d |
Binary file not shown.
|
Before Width: | Height: | Size: 2.1 MiB After Width: | Height: | Size: 1.4 MiB |
3
.gitignore
vendored
3
.gitignore
vendored
@@ -45,6 +45,9 @@ test/vendor/*
|
||||
!/log/index.php
|
||||
!/log/web.config
|
||||
|
||||
# PHPUnit cache file
|
||||
/test/.phpunit.result.cache
|
||||
|
||||
|
||||
# Jetbrains
|
||||
/.idea/**
|
||||
|
||||
@@ -52,26 +52,26 @@ Here are the branches we use and their meaning :
|
||||
|
||||
For example, if no version is currently prepared for shipping we could have:
|
||||
|
||||
- `develop` containing future 3.0.0 version
|
||||
- `develop` containing future 3.1.0 version
|
||||
- `support/3.0`: 3.0.x maintenance version
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
In this example, when 3.0.0-beta is shipped that will become:
|
||||
In this example, when 3.1.0-beta is shipped that will become:
|
||||
|
||||
- `develop`: future 3.1.0 version
|
||||
- `release/3.0.0`: 3.0.0-beta
|
||||
- `develop`: future 3.2.0 version
|
||||
- `release/3.1.0`: 3.1.0-beta
|
||||
- `support/3.0`: 3.0.x maintenance version
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
And when 3.0.0 final will be out:
|
||||
|
||||
- `develop`: future 3.1.0 version
|
||||
- `support/3.0`: 3.0.x maintenance version (will host developments for 3.0.1)
|
||||
- `develop`: future 3.2.0 version
|
||||
- `support/3.1`: 3.1.x maintenance version (will host developments for 3.1.1)
|
||||
- `support/3.0`: 3.0.x maintenance version
|
||||
- `support/2.7`: 2.7.x maintenance version
|
||||
- `support/2.6`: 2.6.x maintenance version
|
||||
- `support/2.5`: 2.5.x maintenance version
|
||||
|
||||
Also note that we have a "micro-version" concept : each of those versions have a very small amount of modifications. They are made from
|
||||
`support/*` branches as well. For example 2.6.2-1 and 2.6.2-2 were made from the `support/2.6.2` branch.
|
||||
|
||||
11
README.md
11
README.md
@@ -78,18 +78,19 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
|
||||
- Alves, David
|
||||
- Beck, Pedro
|
||||
- Beer, Christian (a.k.a [@ChristianBeer](https://www.github.com/ChristianBeer))
|
||||
- Bilger, Jean-François
|
||||
- Bostoen, Jeffrey (a.k.a @jbostoen)
|
||||
- Bostoen, Jeffrey (a.k.a [@jbostoen](https://www.github.com/jbostoen))
|
||||
- Cardoso, Anderson
|
||||
- Cassaro, Bruno
|
||||
- Casteleyn, Thomas (a.k.a @Hipska)
|
||||
- Casteleyn, Thomas (a.k.a [@Hipska](https://www.github.com/Hipska))
|
||||
- Castro, Randall Badilla
|
||||
- Colantoni, Maria Laura
|
||||
- Couronné, Guy
|
||||
- Dvořák, Lukáš
|
||||
- Goethals, Stefan
|
||||
- Gumble, David
|
||||
- Kaltefleiter, Lars (a.k.a @larhip)
|
||||
- Kaltefleiter, Lars (a.k.a [@larhip](https://www.github.com/larhip))
|
||||
- Khamit, Shamil
|
||||
- Kincel, Martin
|
||||
- Konečný, Kamil
|
||||
@@ -98,12 +99,12 @@ We would like to give a special thank you 🤗 to the people from the community
|
||||
- Lazcano, Federico
|
||||
- Lucas, Jonathan
|
||||
- Malik, Remie
|
||||
- Mindêllo de Andrade, Lucas (a.k.a @rokam)
|
||||
- Mindêllo de Andrade, Lucas (a.k.a [@rokam](https://www.github.com/rokam))
|
||||
- Raenker, Martin
|
||||
- Rosenke, Stephan
|
||||
- Seki, Shoji
|
||||
- Shilov, Vladimir
|
||||
- Stukalov, Ilya (a.k.a @ilya-stukalov)
|
||||
- Stukalov, Ilya (a.k.a [@ilya](https://www.github.com/ilya)-stukalov)
|
||||
- Tulio, Marco
|
||||
- Turrubiates, Miguel
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ define('PORTAL_PROFILE_NAME', 'Portal user');
|
||||
class UserRightsBaseClassGUI extends cmdbAbstractObject
|
||||
{
|
||||
// Whenever something changes, reload the privileges
|
||||
|
||||
|
||||
protected function AfterInsert()
|
||||
{
|
||||
UserRights::FlushPrivileges();
|
||||
@@ -59,7 +59,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
}
|
||||
|
||||
protected static $m_aCacheProfiles = null;
|
||||
|
||||
|
||||
public static function DoCreateProfile($sName, $sDescription)
|
||||
{
|
||||
if (is_null(self::$m_aCacheProfiles))
|
||||
@@ -71,7 +71,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
{
|
||||
self::$m_aCacheProfiles[$oProfile->Get('name')] = $oProfile->GetKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$sCacheKey = $sName;
|
||||
if (isset(self::$m_aCacheProfiles[$sCacheKey]))
|
||||
@@ -82,10 +82,10 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
$oNewObj->Set('name', $sName);
|
||||
$oNewObj->Set('description', $sDescription);
|
||||
$iId = $oNewObj->DBInsertNoReload();
|
||||
self::$m_aCacheProfiles[$sCacheKey] = $iId;
|
||||
self::$m_aCacheProfiles[$sCacheKey] = $iId;
|
||||
return $iId;
|
||||
}
|
||||
|
||||
|
||||
function GetGrantAsHtml($oUserRights, $sClass, $sAction)
|
||||
{
|
||||
$bGrant = $oUserRights->GetProfileActionGrant($this->GetKey(), $sClass, $sAction);
|
||||
@@ -102,7 +102,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
return '<span style="background-color: #ffdddd;">'.Dict::S('UI:UserManagement:ActionAllowed:No').'</span>';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function DoShowGrantSumary($oPage)
|
||||
{
|
||||
if ($this->GetRawName() == "Administrator")
|
||||
@@ -114,7 +114,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
|
||||
// Note: for sure, we assume that the instance is derived from UserRightsProfile
|
||||
$oUserRights = UserRights::GetModuleInstance();
|
||||
|
||||
|
||||
$aDisplayData = array();
|
||||
foreach (MetaModel::GetClasses('bizmodel,grant_by_profile') as $sClass)
|
||||
{
|
||||
@@ -123,12 +123,12 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
{
|
||||
$bGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode);
|
||||
if ($bGrant === true)
|
||||
{
|
||||
{
|
||||
$aStimuli[] = '<span title="'.$sStimulusCode.': '.htmlentities($oStimulus->GetDescription(), ENT_QUOTES, 'UTF-8').'">'.htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8').'</span>';
|
||||
}
|
||||
}
|
||||
$sStimuli = implode(', ', $aStimuli);
|
||||
|
||||
|
||||
$aDisplayData[] = array(
|
||||
'class' => MetaModel::GetName($sClass),
|
||||
'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'r'),
|
||||
@@ -140,7 +140,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
'stimuli' => $sStimuli,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$aDisplayConfig = array();
|
||||
$aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+'));
|
||||
$aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+'));
|
||||
@@ -198,7 +198,7 @@ class URP_Profiles extends UserRightsBaseClassGUI
|
||||
* @param $aReasons array To store the reasons why the attribute is read-only (info about the synchro replicas)
|
||||
* @param $sTargetState string The target state in which to evalutate the flags, if empty the current state will be used
|
||||
* @return integer Flags: the binary combination of the flags applicable to this attribute
|
||||
*/
|
||||
*/
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
$iFlags = parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
@@ -404,7 +404,7 @@ class URP_UserOrg extends UserRightsBaseClassGUI
|
||||
{
|
||||
if (!UserRights::IsLoggedIn() || UserRights::IsAdministrator()) { return; }
|
||||
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$oUser = UserRights::GetUserObject();
|
||||
$oAddon = UserRights::GetModuleInstance();
|
||||
$aOrgs = $oAddon->GetUserOrgs($oUser, '');
|
||||
if (count($aOrgs) > 0)
|
||||
@@ -528,7 +528,7 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
$oSearch->AllowAllData();
|
||||
$oCondition = new BinaryExpression(new FieldExpression('userid'), '=', new VariableExpression('userid'));
|
||||
$oSearch->AddConditionExpression($oCondition);
|
||||
|
||||
|
||||
$oUserOrgSet = new DBObjectSet($oSearch, array(), array('userid' => $iUser));
|
||||
while ($oUserOrg = $oUserOrgSet->Fetch())
|
||||
{
|
||||
@@ -738,8 +738,10 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
// load and cache permissions for the current user on the given class
|
||||
//
|
||||
$iUser = $oUser->GetKey();
|
||||
$aTest = @$this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
||||
if (is_array($aTest)) return $aTest;
|
||||
if (isset($this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode])){
|
||||
$aTest = $this->m_aObjectActionGrants[$iUser][$sClass][$iActionCode];
|
||||
if (is_array($aTest)) return $aTest;
|
||||
}
|
||||
|
||||
$sAction = self::$m_aActionCodes[$iActionCode];
|
||||
|
||||
@@ -905,8 +907,8 @@ class UserRightsProfile extends UserRightsAddOnAPI
|
||||
|
||||
/**
|
||||
* Find out which attribute is corresponding the the dimension 'owner org'
|
||||
* returns null if no such attribute has been found (no filtering should occur)
|
||||
*/
|
||||
* returns null if no such attribute has been found (no filtering should occur)
|
||||
*/
|
||||
public static function GetOwnerOrganizationAttCode($sClass)
|
||||
{
|
||||
$sAttCode = null;
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
|
||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/AjaxPage.php, now loadable using autoloader');
|
||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/AjaxPage.php, now loadable using autoloader');
|
||||
|
||||
/**
|
||||
* Class ajax_page
|
||||
|
||||
@@ -1402,11 +1402,11 @@ interface iBackofficeDictEntriesPrefixesExtension
|
||||
/**
|
||||
* Implement this interface to add content to any enhanced portal page
|
||||
*
|
||||
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @since 2.4.0
|
||||
*
|
||||
* @since 2.4.0 interface creation
|
||||
* @since 2.7.0 change method signatures due to Silex to Symfony migration
|
||||
*/
|
||||
interface iPortalUIExtension
|
||||
{
|
||||
@@ -1479,7 +1479,11 @@ interface iPortalUIExtension
|
||||
}
|
||||
|
||||
/**
|
||||
* IMPORTANT! Experimental API, may be removed at anytime, we don't recommend to use it just now!
|
||||
* Extend this class instead of iPortalUIExtension if you don't need to overload all methods
|
||||
*
|
||||
* @api
|
||||
* @package Extensibility
|
||||
* @since 2.4.0
|
||||
*/
|
||||
abstract class AbstractPortalUIExtension implements iPortalUIExtension
|
||||
{
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CaptureWebPage.php, now loadable using autoloader');
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CLIPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CLIPage.php, now loadable using autoloader');
|
||||
@@ -60,11 +60,11 @@ require_once(APPROOT.'application/ui.linksdirectwidget.class.inc.php');
|
||||
require_once(APPROOT.'application/ui.passwordwidget.class.inc.php');
|
||||
require_once(APPROOT.'application/ui.extkeywidget.class.inc.php');
|
||||
require_once(APPROOT.'application/ui.htmleditorwidget.class.inc.php');
|
||||
require_once(APPROOT.'sources/application/search/searchform.class.inc.php');
|
||||
require_once(APPROOT.'sources/application/search/criterionparser.class.inc.php');
|
||||
require_once(APPROOT.'sources/application/search/criterionconversionabstract.class.inc.php');
|
||||
require_once(APPROOT.'sources/application/search/criterionconversion/criteriontooql.class.inc.php');
|
||||
require_once(APPROOT.'sources/application/search/criterionconversion/criteriontosearchform.class.inc.php');
|
||||
require_once(APPROOT.'sources/Application/Search/searchform.class.inc.php');
|
||||
require_once(APPROOT.'sources/Application/Search/criterionparser.class.inc.php');
|
||||
require_once(APPROOT.'sources/Application/Search/criterionconversionabstract.class.inc.php');
|
||||
require_once(APPROOT.'sources/Application/Search/CriterionConversion/criteriontooql.class.inc.php');
|
||||
require_once(APPROOT.'sources/Application/Search/CriterionConversion/criteriontosearchform.class.inc.php');
|
||||
|
||||
/**
|
||||
* Class cmdbAbstractObject
|
||||
@@ -509,32 +509,6 @@ HTML
|
||||
return $aHeaderBlocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display history tab of an object
|
||||
*
|
||||
* @deprecated 3.0.0 will be removed in 3.1, see N°3824
|
||||
*
|
||||
* @param bool $bEditMode
|
||||
* @param int $iLimitCount
|
||||
* @param int $iLimitStart
|
||||
*
|
||||
* @param \WebPage $oPage
|
||||
*
|
||||
* @throws \CoreException
|
||||
*
|
||||
*/
|
||||
public function DisplayBareHistory(WebPage $oPage, $bEditMode = false, $iLimitCount = 0, $iLimitStart = 0)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
// history block (with as a tab)
|
||||
$oHistoryFilter = new DBObjectSearch('CMDBChangeOp');
|
||||
$oHistoryFilter->AddCondition('objkey', $this->GetKey(), '=');
|
||||
$oHistoryFilter->AddCondition('objclass', get_class($this), '=');
|
||||
$oBlock = new HistoryBlock($oHistoryFilter, 'table', false);
|
||||
$oBlock->SetLimit($iLimitCount, $iLimitStart);
|
||||
$oBlock->Display($oPage, 'history');
|
||||
}
|
||||
|
||||
/**
|
||||
* Display properties tab of an object
|
||||
*
|
||||
@@ -1186,8 +1160,6 @@ HTML
|
||||
$oPage->SetCurrentTab('UI:PropertiesTab');
|
||||
$this->DisplayBareProperties($oPage, $bEditMode);
|
||||
$this->DisplayBareRelations($oPage, $bEditMode);
|
||||
// TODO 3.0.0: What to do with this?
|
||||
//$this->DisplayBareHistory($oPage, $bEditMode);
|
||||
|
||||
// Note: Adding the JS snippet which enables the image upload should have been done directly by the ActivityPanel which would have kept the independance principle
|
||||
// of the UIBlock. For now we keep it this way in order to move on and trace this known limitation in N°3736.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/CSVPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/CSVPage.php, now loadable using autoloader');
|
||||
@@ -789,6 +789,7 @@ class RuntimeDashboard extends Dashboard
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @return bool $bIsNew
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function Save()
|
||||
@@ -798,6 +799,7 @@ class RuntimeDashboard extends Dashboard
|
||||
$oUDSearch->AddCondition('user_id', UserRights::GetUserId(), '=');
|
||||
$oUDSearch->AddCondition('menu_code', $this->sId, '=');
|
||||
$oUDSet = new DBObjectSet($oUDSearch);
|
||||
$bIsNew = false;
|
||||
if ($oUDSet->Count() > 0)
|
||||
{
|
||||
// Assuming there is at most one couple {user, menu}!
|
||||
@@ -811,10 +813,12 @@ class RuntimeDashboard extends Dashboard
|
||||
$oUserDashboard->Set('user_id', UserRights::GetUserId());
|
||||
$oUserDashboard->Set('menu_code', $this->sId);
|
||||
$oUserDashboard->Set('contents', $sXml);
|
||||
$bIsNew = true;
|
||||
}
|
||||
utils::PushArchiveMode(false);
|
||||
$oUserDashboard->DBWrite();
|
||||
utils::PopArchiveMode();
|
||||
return $bIsNew;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="AbstractResource" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
|
||||
@@ -476,7 +476,7 @@ class DisplayBlock
|
||||
$oExceptionAlert = AlertUIBlockFactory::MakeForFailure('Cannot display results', $sExceptionContent);
|
||||
$oHtml->AddSubBlock($oExceptionAlert);
|
||||
}
|
||||
IssueLog::Error('Exception during GetDisplay: '.$e->getMessage());
|
||||
ExceptionLog::LogException($e);
|
||||
}
|
||||
} else {
|
||||
// render it as an Ajax (asynchronous) call
|
||||
@@ -1054,6 +1054,11 @@ JS
|
||||
$oBlock->AddSubBlock($oPill);
|
||||
}
|
||||
$aExtraParams['query_params'] = $this->m_oFilter->GetInternalParams();
|
||||
if(isset($aExtraParams['query_params']['this->object()'])){
|
||||
$aExtraParams['query_params']['this->class'] = get_class($aExtraParams['query_params']['this->object()']);
|
||||
$aExtraParams['query_params']['this->id'] = $aExtraParams['query_params']['this->object()']->GetKey();
|
||||
unset($aExtraParams['query_params']['this->object()']);
|
||||
}
|
||||
$aRefreshParams = ['filter' => $this->m_oFilter->ToOQL(), "extra_params" => json_encode($aExtraParams)];
|
||||
$oBlock->SetJSRefresh(
|
||||
"$('#".$oBlock->GetId()."').block();
|
||||
@@ -1700,162 +1705,6 @@ JS
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper class to manage 'blocks' of HTML pieces that are parts of a page and contain some list of cmdb objects
|
||||
*
|
||||
* Each block is actually rendered as a <div></div> tag that can be rendered synchronously
|
||||
* or as a piece of Javascript/JQuery/Ajax that will get its content from another page (ajax.render.php).
|
||||
* The list of cmdbObjects to be displayed into the block is defined by a filter
|
||||
* Right now the type of display is either: list, count or details
|
||||
* - list produces a table listing the objects
|
||||
* - count produces a paragraphs with a sentence saying 'cont' objects found
|
||||
* - details display (as table) the details of each object found (best if only one)
|
||||
*
|
||||
* @deprecated 3.0.0 will be removed in 3.1, see N°3824
|
||||
*/
|
||||
class HistoryBlock extends DisplayBlock
|
||||
{
|
||||
protected $iLimitCount;
|
||||
protected $iLimitStart;
|
||||
|
||||
public function __construct(DBSearch $oFilter, $sStyle = 'list', $bAsynchronous = false, $aParams = array(), $oSet = null)
|
||||
{
|
||||
DeprecatedCallsLog::NotifyDeprecatedPhpMethod();
|
||||
parent::__construct($oFilter, $sStyle, $bAsynchronous, $aParams, $oSet);
|
||||
$this->iLimitStart = 0;
|
||||
$this->iLimitCount = 0;
|
||||
}
|
||||
|
||||
public function SetLimit($iCount, $iStart = 0)
|
||||
{
|
||||
$this->iLimitStart = $iStart;
|
||||
$this->iLimitCount = $iCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \WebPage $oPage
|
||||
* @param array $aExtraParams
|
||||
* @param string $sId
|
||||
*
|
||||
* @return string
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \DictExceptionMissingString
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*
|
||||
* @since 2.7.7 3.0.1 3.1.0 N°3129 Remove default value for $aExtraParams and add type hinting for PHP 8.0 compatibility
|
||||
* (var is unused, and all calls were already made using a default value)
|
||||
*/
|
||||
public function GetRenderContent(WebPage $oPage, array $aExtraParams, string $sId)
|
||||
{
|
||||
$sHtml = '';
|
||||
$bTruncated = false;
|
||||
$oSet = new CMDBObjectSet($this->m_oFilter, array('date' => false));
|
||||
if (!$oPage->IsPrintableVersion()) {
|
||||
if (($this->iLimitStart > 0) || ($this->iLimitCount > 0)) {
|
||||
$oSet->SetLimit($this->iLimitCount, $this->iLimitStart);
|
||||
if (($this->iLimitCount - $this->iLimitStart) < $oSet->Count()) {
|
||||
$bTruncated = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
$sHtml .= "<!-- filter: ".($this->m_oFilter->ToOQL())."-->\n";
|
||||
switch ($this->m_sStyle) {
|
||||
case 'toggle':
|
||||
// First the latest change that the user is allowed to see
|
||||
do {
|
||||
$oLatestChangeOp = $oSet->Fetch();
|
||||
} while (is_object($oLatestChangeOp) && ($oLatestChangeOp->GetDescription() == ''));
|
||||
|
||||
if (is_object($oLatestChangeOp)) {
|
||||
// There is one change in the list... only when the object has been created !
|
||||
$sDate = $oLatestChangeOp->GetAsHTML('date');
|
||||
$oChange = MetaModel::GetObject('CMDBChange', $oLatestChangeOp->Get('change'));
|
||||
$sUserInfo = $oChange->GetAsHTML('userinfo');
|
||||
$sHtml .= $oPage->GetStartCollapsibleSection(Dict::Format('UI:History:LastModified_On_By', $sDate, $sUserInfo));
|
||||
$sHtml .= $this->GetHistoryTable($oPage, $oSet);
|
||||
$sHtml .= $oPage->GetEndCollapsibleSection();
|
||||
}
|
||||
break;
|
||||
|
||||
case 'table':
|
||||
default:
|
||||
if ($bTruncated)
|
||||
{
|
||||
$sFilter = htmlentities($this->m_oFilter->serialize(), ENT_QUOTES, 'UTF-8');
|
||||
$sHtml .= '<div id="history_container"><p>';
|
||||
$sHtml .= Dict::Format('UI:TruncatedResults', $this->iLimitCount, $oSet->Count());
|
||||
$sHtml .= ' ';
|
||||
$sHtml .= '<a href="#" onclick="DisplayHistory(\'#history_container\', \''.$sFilter.'\', 0, 0); return false;">'.Dict::S('UI:DisplayAll').'</a>';
|
||||
$sHtml .= $this->GetHistoryTable($oPage, $oSet);
|
||||
$sHtml .= '</p></div>';
|
||||
$oPage->add_ready_script("$('#{$sId} table.listResults tr:last td').addClass('truncated');");
|
||||
}
|
||||
else
|
||||
{
|
||||
$sHtml .= $this->GetHistoryTable($oPage, $oSet);
|
||||
}
|
||||
$oPage->add_ready_script(InlineImage::FixImagesWidth());
|
||||
|
||||
$oPage->add_ready_script("$('.case-log-history-entry-toggle').on('click', function () { $(this).closest('.case-log-history-entry').toggleClass('expanded');});");
|
||||
$oPage->add_ready_script(
|
||||
<<<EOF
|
||||
$('.history_entry').each(function() {
|
||||
var jMe = $(this);
|
||||
var oContent = $(this).find('.history_html_content');
|
||||
if (jMe.height() < oContent.height())
|
||||
{
|
||||
jMe.prepend('<span class="history_truncated_toggler"></span>');
|
||||
jMe.find('.history_truncated_toggler').on('click', function() {
|
||||
jMe.toggleClass('history_entry_truncated');
|
||||
});
|
||||
}
|
||||
});
|
||||
EOF
|
||||
);
|
||||
}
|
||||
return new Html($sHtml);
|
||||
}
|
||||
|
||||
protected function GetHistoryTable(WebPage $oPage, DBObjectSet $oSet)
|
||||
{
|
||||
$sHtml = '';
|
||||
// First the latest change that the user is allowed to see
|
||||
$oSet->Rewind(); // Reset the pointer to the beginning of the set
|
||||
$aChanges = array();
|
||||
while($oChangeOp = $oSet->Fetch())
|
||||
{
|
||||
$sChangeDescription = $oChangeOp->GetDescription();
|
||||
if ($sChangeDescription != '')
|
||||
{
|
||||
// The change is visible for the current user
|
||||
$changeId = $oChangeOp->Get('change');
|
||||
$aChanges[$changeId]['date'] = $oChangeOp->Get('date');
|
||||
$aChanges[$changeId]['userinfo'] = $oChangeOp->Get('userinfo');
|
||||
if (!isset($aChanges[$changeId]['log']))
|
||||
{
|
||||
$aChanges[$changeId]['log'] = array();
|
||||
}
|
||||
$aChanges[$changeId]['log'][] = $sChangeDescription;
|
||||
}
|
||||
}
|
||||
$aAttribs = array('date' => array('label' => Dict::S('UI:History:Date'), 'description' => Dict::S('UI:History:Date+')),
|
||||
'userinfo' => array('label' => Dict::S('UI:History:User'), 'description' => Dict::S('UI:History:User+')),
|
||||
'log' => array('label' => Dict::S('UI:History:Changes') , 'description' => Dict::S('UI:History:Changes+')),
|
||||
);
|
||||
$aValues = array();
|
||||
foreach($aChanges as $aChange)
|
||||
{
|
||||
$aValues[] = array('date' => AttributeDateTime::GetFormat()->Format($aChange['date']), 'userinfo' => htmlentities($aChange['userinfo'], ENT_QUOTES, 'UTF-8'), 'log' => "<ul><li>".implode('</li><li>', $aChange['log'])."</li></ul>");
|
||||
}
|
||||
$sHtml .= $oPage->GetTable($aAttribs, $aValues);
|
||||
return $sHtml;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Displays the 'Actions' menu for a given (list of) object(s)
|
||||
* The 'style' of the list (see constructor of DisplayBlock) can be either 'list' or 'details'
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/ErrorPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/ErrorPage.php, now loadable using autoloader');
|
||||
@@ -1272,7 +1272,7 @@ class DesignerComboField extends DesignerFormField
|
||||
$sChecked = $this->defaultValue ? 'checked' : '';
|
||||
$sMandatory = $this->bMandatory ? 'true' : 'false';
|
||||
$sReadOnly = $this->IsReadOnly() ? 'disabled="disabled"' : '';
|
||||
if ($this->IsSorted())
|
||||
if ($this->IsSorted() && isset($this->aAllowedValues) )
|
||||
{
|
||||
asort($this->aAllowedValues);
|
||||
}
|
||||
@@ -1320,19 +1320,17 @@ class DesignerComboField extends DesignerFormField
|
||||
$sHtml .= "<option value=\"\">".$this->sNullLabel."</option>";
|
||||
}
|
||||
}
|
||||
foreach($this->aAllowedValues as $sKey => $sDisplayValue)
|
||||
{
|
||||
if ($this->bMultipleSelection)
|
||||
{
|
||||
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
|
||||
if ( isset($this->aAllowedValues) ) {
|
||||
foreach ($this->aAllowedValues as $sKey => $sDisplayValue) {
|
||||
if ($this->bMultipleSelection) {
|
||||
$sSelected = in_array($sKey, $this->defaultValue) ? 'selected' : '';
|
||||
} else {
|
||||
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
|
||||
}
|
||||
// Quick and dirty: display the menu parents as a tree
|
||||
$sHtmlValue = str_replace(' ', ' ', $sDisplayValue);
|
||||
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
|
||||
}
|
||||
else
|
||||
{
|
||||
$sSelected = ($sKey == $this->defaultValue) ? 'selected' : '';
|
||||
}
|
||||
// Quick and dirty: display the menu parents as a tree
|
||||
$sHtmlValue = str_replace(' ', ' ', htmlentities($sDisplayValue, ENT_QUOTES, 'UTF-8'));
|
||||
$sHtml .= "<option value=\"".htmlentities($sKey, ENT_QUOTES, 'UTF-8')."\" $sSelected>$sHtmlValue</option>";
|
||||
}
|
||||
$sHtml .= "</select></span>";
|
||||
if ($this->bOtherChoices)
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWebPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
// cannot notify depreciation for now as this is still MASSIVELY used in iTop core !
|
||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWebPage.php, now loadable using autoloader');
|
||||
//DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWebPage.php, now loadable using autoloader');
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/iTopWizardWebPage.php, now loadable using autoloader');
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/NiceWebPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/NiceWebPage.php, now loadable using autoloader');
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/PDFPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/PDFPage.php, now loadable using autoloader');
|
||||
@@ -18,8 +18,7 @@
|
||||
*/
|
||||
|
||||
use Combodo\iTop\Application\UI\Base\Component\Alert\AlertUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Field\Field;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Field\FieldUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\FieldSet\FieldSetUIBlockFactory;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Html\Html;
|
||||
use Combodo\iTop\Application\UI\Base\Component\Input\TextArea;
|
||||
|
||||
@@ -51,6 +50,7 @@ abstract class Query extends cmdbAbstractObject
|
||||
"is_null_allowed" => false,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeText("description", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "description",
|
||||
@@ -68,6 +68,41 @@ abstract class Query extends cmdbAbstractObject
|
||||
'display_style' => 'radio_horizontal',
|
||||
)));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeInteger("export_count", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "export_count",
|
||||
"default_value" => 0,
|
||||
"is_null_allowed" => false,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeDateTime("export_last_date", array(
|
||||
"allowed_values" => null,
|
||||
"sql" => "export_last_date",
|
||||
"default_value" => null,
|
||||
"is_null_allowed" => true,
|
||||
"depends_on" => array(),
|
||||
)));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalKey("export_last_user_id",
|
||||
array(
|
||||
"targetclass"=>'User',
|
||||
"allowed_values"=>null,
|
||||
"sql"=>'user_id',
|
||||
"is_null_allowed"=>true,
|
||||
"depends_on"=>array(),
|
||||
"display_style"=>'select',
|
||||
"always_load_in_tables"=>false,
|
||||
"on_target_delete"=>DEL_SILENT
|
||||
)));
|
||||
|
||||
MetaModel::Init_AddAttribute(new AttributeExternalField("export_last_user_contact",
|
||||
array(
|
||||
"allowed_values"=>null,
|
||||
"extkey_attcode"=> "export_last_user_id",
|
||||
"target_attcode"=>"contactid"
|
||||
)));
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details',
|
||||
array('name', 'is_template', 'description')); // Attributes to be displayed for the complete details
|
||||
@@ -78,6 +113,54 @@ abstract class Query extends cmdbAbstractObject
|
||||
array('name', 'description', 'is_template')); // Criteria of the default search form
|
||||
// MetaModel::Init_SetZListItems('advanced_search', array('name')); // Criteria of the advanced search form
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public function GetAttributeFlags($sAttCode, &$aReasons = array(), $sTargetState = '')
|
||||
{
|
||||
// read only attribute
|
||||
if (in_array($sAttCode, ['export_count', 'export_last_date', 'export_last_user_id'])){
|
||||
return OPT_ATT_READONLY;
|
||||
}
|
||||
|
||||
return parent::GetAttributeFlags($sAttCode, $aReasons, $sTargetState);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return export url.
|
||||
*
|
||||
* @param array|null $aValues optional values for the query
|
||||
*
|
||||
* @return string|null
|
||||
* @since 3.1.0
|
||||
*/
|
||||
abstract public function GetExportUrl(array $aValues = null) : ?string;
|
||||
|
||||
/**
|
||||
* Update last export information.
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MySQLException
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public function UpdateLastExportInformation() : void
|
||||
{
|
||||
// last export information
|
||||
$this->Set('export_last_date', date(AttributeDateTime::GetSQLFormat()));
|
||||
$this->Set('export_last_user_id', UserRights::GetUserObject());
|
||||
$this->DBUpdate();
|
||||
|
||||
// increment usage counter
|
||||
$this->DBIncrement('export_count');
|
||||
}
|
||||
}
|
||||
|
||||
class QueryOQL extends Query
|
||||
@@ -116,13 +199,51 @@ class QueryOQL extends Query
|
||||
|
||||
// Display lists
|
||||
MetaModel::Init_SetZListItems('details',
|
||||
array('name', 'is_template', 'description', 'oql', 'fields')); // Attributes to be displayed for the complete details
|
||||
array(
|
||||
'col:col1' => array('fieldset:Query:baseinfo' => array('name', 'is_template', 'description', 'oql', 'fields')),
|
||||
'col:col2' => array('fieldset:Query:exportInfo' => array('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', array('description')); // Attributes to be displayed for a list
|
||||
// Search criteria
|
||||
MetaModel::Init_SetZListItems('standard_search',
|
||||
array('name', 'description', 'is_template', 'fields', 'oql')); // Criteria of the std search form
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
public function GetExportUrl(array $aValues = null) : ?string
|
||||
{
|
||||
try{
|
||||
// retrieve attributes
|
||||
$sFields = trim($this->Get('fields'));
|
||||
$sOql = $this->Get('oql');
|
||||
|
||||
// construct base url depending on version
|
||||
$bExportV1Recommended = ($sFields == '');
|
||||
if ($bExportV1Recommended) {
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export.php?format=spreadsheet&login_mode=basic&query='.$this->GetKey();
|
||||
}
|
||||
else{
|
||||
$sUrl = utils::GetAbsoluteUrlAppRoot().'webservices/export-v2.php?format=spreadsheet&login_mode=basic&date_format='.urlencode((string)AttributeDateTime::GetFormat()).'&query='.$this->GetKey();
|
||||
}
|
||||
|
||||
// search object from OQL
|
||||
$oSearch = DBObjectSearch::FromOQL($sOql);
|
||||
|
||||
// inject parameters
|
||||
$aParameters = $oSearch->GetQueryParams();
|
||||
foreach ($aParameters as $sParam => $val) {
|
||||
$paramValue = ($aValues === null || $aValues[$sParam] === null) ? $sParam : $aValues[$sParam];
|
||||
$sUrl .= '&arg_' . $sParam . '=' . $paramValue;
|
||||
}
|
||||
|
||||
return $sUrl;
|
||||
}
|
||||
catch(Exception $e){
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function DisplayBareProperties(WebPage $oPage, $bEditMode = false, $sPrefix = '', $aExtraParams = array())
|
||||
{
|
||||
$aFieldsMap = parent::DisplayBareProperties($oPage, $bEditMode, $sPrefix, $aExtraParams);
|
||||
@@ -152,9 +273,11 @@ class QueryOQL extends Query
|
||||
$sUrl .= '&arg_'.$sParam.'=["'.$sParam.'"]';
|
||||
}
|
||||
|
||||
// add text area inside field set
|
||||
$oFieldSet = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:Query:UrlForExcel'));
|
||||
$oTextArea = new TextArea("", $sUrl, null, 80, 3);
|
||||
$oFieldUrl = FieldUIBlockFactory::MakeFromObject(Dict::S('UI:Query:UrlForExcel'), $oTextArea, Field::ENUM_FIELD_LAYOUT_LARGE);
|
||||
$oPage->AddSubBlock($oFieldUrl);
|
||||
$oFieldSet->AddSubBlock($oTextArea);
|
||||
$oPage->AddSubBlock($oFieldSet);
|
||||
|
||||
if (count($aParameters) == 0) {
|
||||
$oBlock = new DisplayBlock($oSearch, 'list');
|
||||
@@ -178,6 +301,7 @@ class QueryOQL extends Query
|
||||
return $aFieldsMap;
|
||||
}
|
||||
|
||||
|
||||
// Rolled back until 'fields' can be properly managed by AttributeQueryAttCodeSet
|
||||
//
|
||||
// public function ComputeValues()
|
||||
|
||||
@@ -234,7 +234,6 @@ class DisplayTemplate
|
||||
$sTemplate = '<div class="page_header">
|
||||
<div class="actions_details"><a href="#"><span>Actions</span></a></div>
|
||||
<h1>$class$: <span class="hilite">$name$</span></h1>
|
||||
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/oql">SELECT CMDBChangeOp WHERE objkey = $id$ AND objclass = \'$class$\'</itopblock>
|
||||
</div>
|
||||
<img src="../../images/connect_to_network.png" style="margin-top:-10px; margin-right:10px; float:right">
|
||||
<itoptabs>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
<div class="page_header">
|
||||
<itopblock blockclass="MenuBlock" type="popup" encoding="text/oql" label="Actions">SELECT $class$ WHERE id = $id$</itopblock>
|
||||
<h1>$class$: <span class="hilite">$name$</span></h1>
|
||||
<itopblock blockclass="HistoryBlock" type="toggle" encoding="text/oql">SELECT CMDBChangeOp WHERE objkey = $id$ AND objclass = '$class$'</itopblock>
|
||||
</div>
|
||||
<img src="../../images/clean.png" style="margin-top:-20px; margin-right:10px; float:right">
|
||||
<itopblock blockclass="DisplayBlock" asynchronous="false" type="bare_details" encoding="text/oql">SELECT $class$ WHERE id = $id$</itopblock>
|
||||
|
||||
@@ -975,7 +975,7 @@ HTML
|
||||
$oPage->add_ready_script(<<<JS
|
||||
$('#ac_create_{$this->iId}').dialog({ width: 'auto', height: 'auto', maxHeight: $(window).height() - 50, autoOpen: false, modal: true});
|
||||
$('#dcr_{$this->iId} form').removeAttr('onsubmit');
|
||||
$('#dcr_{$this->iId} form').on('submit.uilinksWizard', oACWidget_{$this->iId}.DoCreateObject);
|
||||
$('#dcr_{$this->iId} form').find('button[type="submit"]').on('click', oACWidget_{$this->iId}.DoCreateObject);
|
||||
JS
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1944,28 +1944,18 @@ class utils
|
||||
|
||||
return $sCss;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the size of an image from a string.
|
||||
*
|
||||
* @see \getimagesizefromstring()
|
||||
* @param $sImageData string The image data, as a string.
|
||||
*
|
||||
* @return array|false
|
||||
*/
|
||||
public static function GetImageSize($sImageData)
|
||||
{
|
||||
if (function_exists('getimagesizefromstring')) // PHP 5.4.0 or higher
|
||||
{
|
||||
$aRet = @getimagesizefromstring($sImageData);
|
||||
}
|
||||
else if(ini_get('allow_url_fopen'))
|
||||
{
|
||||
// work around to avoid creating a tmp file
|
||||
$sUri = 'data://application/octet-stream;base64,'.base64_encode($sImageData);
|
||||
$aRet = @getimagesize($sUri);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Damned, need to create a tmp file
|
||||
$sTempFile = tempnam(SetupUtils::GetTmpDir(), 'img-');
|
||||
@file_put_contents($sTempFile, $sImageData);
|
||||
$aRet = @getimagesize($sTempFile);
|
||||
@unlink($sTempFile);
|
||||
}
|
||||
return $aRet;
|
||||
return @getimagesizefromstring($sImageData);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/WebPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/WebPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/WebPage.php, now loadable using autoloader');
|
||||
@@ -1,8 +1,8 @@
|
||||
<?php
|
||||
/**
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/application/WebPage/XMLPage.php, now loadable using autoloader
|
||||
* @deprecated will be removed in 3.1.0 - moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
*/
|
||||
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/application/WebPage/XMLPage.php, now loadable using autoloader');
|
||||
DeprecatedCallsLog::NotifyDeprecatedFile('moved to sources/Application/WebPage/XMLPage.php, now loadable using autoloader');
|
||||
@@ -11,7 +11,7 @@ define('APPCONF', APPROOT.'conf/');
|
||||
*
|
||||
* @see ITOP_CORE_VERSION to get full iTop core version
|
||||
*/
|
||||
define('ITOP_DESIGN_LATEST_VERSION', '3.0');
|
||||
define('ITOP_DESIGN_LATEST_VERSION', '3.1');
|
||||
|
||||
/**
|
||||
* Constant containing the iTop core version, whatever application was built
|
||||
@@ -23,6 +23,6 @@ define('ITOP_DESIGN_LATEST_VERSION', '3.0');
|
||||
* @used-by utils::GetItopVersionWikiSyntax()
|
||||
* @used-by iTopModulesPhpVersionIntegrationTest
|
||||
*/
|
||||
define('ITOP_CORE_VERSION', '3.0.1');
|
||||
define('ITOP_CORE_VERSION', '3.1.0');
|
||||
|
||||
require_once APPROOT.'bootstrap.inc.php';
|
||||
|
||||
@@ -11,11 +11,12 @@
|
||||
"ext-mysqli": "*",
|
||||
"ext-soap": "*",
|
||||
"combodo/tcpdf": "6.3.5",
|
||||
"laminas/laminas-mail": "^2.12",
|
||||
"laminas/laminas-servicemanager": "^3.5",
|
||||
"nikic/php-parser": "^4.12.0",
|
||||
"pear/archive_tar": "1.4.14",
|
||||
"pelago/emogrifier": "3.1.0",
|
||||
"scssphp/scssphp": "1.0.6",
|
||||
"swiftmailer/swiftmailer": "5.4.12",
|
||||
"symfony/console": "~3.4.47",
|
||||
"symfony/dotenv": "~3.4.47",
|
||||
"symfony/framework-bundle": "~3.4.47",
|
||||
|
||||
632
composer.lock
generated
632
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": "4c5cdd1e0feb4abaab8f86959ffc7a64",
|
||||
"content-hash": "932a981993f694ebe4e382219fb40008",
|
||||
"packages": [
|
||||
{
|
||||
"name": "combodo/tcpdf",
|
||||
@@ -66,6 +66,530 @@
|
||||
"homepage": "https://github.com/combodo-itop-libs/TCPDF",
|
||||
"time": "2020-09-28T12:19:09+00:00"
|
||||
},
|
||||
{
|
||||
"name": "container-interop/container-interop",
|
||||
"version": "1.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/container-interop/container-interop.git",
|
||||
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/container-interop/container-interop/zipball/79cbf1341c22ec75643d841642dd5d6acd83bdb8",
|
||||
"reference": "79cbf1341c22ec75643d841642dd5d6acd83bdb8",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Interop\\Container\\": "src/Interop/Container/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"description": "Promoting the interoperability of container objects (DIC, SL, etc.)",
|
||||
"homepage": "https://github.com/container-interop/container-interop",
|
||||
"support": {
|
||||
"issues": "https://github.com/container-interop/container-interop/issues",
|
||||
"source": "https://github.com/container-interop/container-interop/tree/master"
|
||||
},
|
||||
"abandoned": "psr/container",
|
||||
"time": "2017-02-14T19:40:03+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-loader",
|
||||
"version": "2.6.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-loader.git",
|
||||
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-loader/zipball/5d01c2c237ae9e68bec262f339947e2ea18979bc",
|
||||
"reference": "5d01c2c237ae9e68bec262f339947e2ea18979bc",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-loader": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.4"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.6.x-dev",
|
||||
"dev-develop": "2.7.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Loader\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Autoloading and plugin loading strategies",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"loader"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-loader/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-loader/issues",
|
||||
"rss": "https://github.com/laminas/laminas-loader/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-loader"
|
||||
},
|
||||
"time": "2019-12-31T17:18:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-mail",
|
||||
"version": "2.12.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-mail.git",
|
||||
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-mail/zipball/ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
|
||||
"reference": "ed5b36a0deef4ffafe6138c2ae9cafcffafab856",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-iconv": "*",
|
||||
"laminas/laminas-loader": "^2.5",
|
||||
"laminas/laminas-mime": "^2.5",
|
||||
"laminas/laminas-stdlib": "^2.7 || ^3.0",
|
||||
"laminas/laminas-validator": "^2.10.2",
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^7.1",
|
||||
"true/punycode": "^2.1"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-mail": "^2.10.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"laminas/laminas-config": "^2.6",
|
||||
"laminas/laminas-crypt": "^2.6 || ^3.0",
|
||||
"laminas/laminas-servicemanager": "^3.2.1",
|
||||
"phpunit/phpunit": "^7.5.20"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-crypt": "Crammd5 support in SMTP Auth",
|
||||
"laminas/laminas-servicemanager": "^2.7.10 || ^3.3.1 when using SMTP to deliver messages"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laminas": {
|
||||
"component": "Laminas\\Mail",
|
||||
"config-provider": "Laminas\\Mail\\ConfigProvider"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Mail\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"mail"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-mail/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-mail/issues",
|
||||
"rss": "https://github.com/laminas/laminas-mail/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-mail"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2020-12-31T11:41:57+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-mime",
|
||||
"version": "2.7.4",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-mime.git",
|
||||
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-mime/zipball/e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
|
||||
"reference": "e45a7d856bf7b4a7b5bd00d6371f9961dc233add",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laminas/laminas-stdlib": "^2.7 || ^3.0",
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-mime": "^2.7.2"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"laminas/laminas-mail": "^2.6",
|
||||
"phpunit/phpunit": "^5.7.27 || ^6.5.14 || ^7.5.20"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-mail": "Laminas\\Mail component"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "2.7.x-dev",
|
||||
"dev-develop": "2.8.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Mime\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Create and parse MIME messages and parts",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"mime"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-mime/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-mime/issues",
|
||||
"rss": "https://github.com/laminas/laminas-mime/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-mime"
|
||||
},
|
||||
"time": "2020-03-29T13:12:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-servicemanager",
|
||||
"version": "3.5.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-servicemanager.git",
|
||||
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-servicemanager/zipball/0669e1eec8d9f61e35a5bc5012796d49f418b259",
|
||||
"reference": "0669e1eec8d9f61e35a5bc5012796d49f418b259",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/container-interop": "^1.2",
|
||||
"laminas/laminas-stdlib": "^3.2.1",
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^5.6 || ^7.0",
|
||||
"psr/container": "^1.0"
|
||||
},
|
||||
"provide": {
|
||||
"container-interop/container-interop-implementation": "^1.2",
|
||||
"psr/container-implementation": "^1.0"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-servicemanager": "^3.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"mikey179/vfsstream": "^1.6.5",
|
||||
"ocramius/proxy-manager": "^1.0 || ^2.0",
|
||||
"phpbench/phpbench": "^0.13.0",
|
||||
"phpunit/phpunit": "^5.7.25 || ^6.4.4"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-stdlib": "laminas-stdlib ^2.5 if you wish to use the MergeReplaceKey or MergeRemoveKey features in Config instances",
|
||||
"ocramius/proxy-manager": "ProxyManager 1.* to handle lazy initialization of services"
|
||||
},
|
||||
"bin": [
|
||||
"bin/generate-deps-for-config-factory",
|
||||
"bin/generate-factory-for-class"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.3-dev",
|
||||
"dev-develop": "4.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\ServiceManager\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Factory-Driven Dependency Injection Container",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"PSR-11",
|
||||
"dependency-injection",
|
||||
"di",
|
||||
"dic",
|
||||
"laminas",
|
||||
"service-manager",
|
||||
"servicemanager"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-servicemanager/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-servicemanager/issues",
|
||||
"rss": "https://github.com/laminas/laminas-servicemanager/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-servicemanager"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-17T16:54:43+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-stdlib",
|
||||
"version": "3.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-stdlib.git",
|
||||
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-stdlib/zipball/2b18347625a2f06a1a485acfbc870f699dbe51c6",
|
||||
"reference": "2b18347625a2f06a1a485acfbc870f699dbe51c6",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^5.6 || ^7.0"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-stdlib": "self.version"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"phpbench/phpbench": "^0.13",
|
||||
"phpunit/phpunit": "^5.7.27 || ^6.5.8 || ^7.1.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "3.2.x-dev",
|
||||
"dev-develop": "3.3.x-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Stdlib\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "SPL extensions, array utilities, error handlers, and more",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"stdlib"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-stdlib/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-stdlib/issues",
|
||||
"rss": "https://github.com/laminas/laminas-stdlib/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-stdlib"
|
||||
},
|
||||
"time": "2019-12-31T17:51:15+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-validator",
|
||||
"version": "2.13.5",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-validator.git",
|
||||
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-validator/zipball/d334dddda43af263d6a7e5024fd2b013cb6981f7",
|
||||
"reference": "d334dddda43af263d6a7e5024fd2b013cb6981f7",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"container-interop/container-interop": "^1.1",
|
||||
"laminas/laminas-stdlib": "^3.2.1",
|
||||
"laminas/laminas-zendframework-bridge": "^1.0",
|
||||
"php": "^7.1"
|
||||
},
|
||||
"replace": {
|
||||
"zendframework/zend-validator": "^2.13.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"laminas/laminas-cache": "^2.6.1",
|
||||
"laminas/laminas-coding-standard": "~1.0.0",
|
||||
"laminas/laminas-config": "^2.6",
|
||||
"laminas/laminas-db": "^2.7",
|
||||
"laminas/laminas-filter": "^2.6",
|
||||
"laminas/laminas-http": "^2.5.4",
|
||||
"laminas/laminas-i18n": "^2.6",
|
||||
"laminas/laminas-math": "^2.6",
|
||||
"laminas/laminas-servicemanager": "^2.7.5 || ^3.0.3",
|
||||
"laminas/laminas-session": "^2.8",
|
||||
"laminas/laminas-uri": "^2.5",
|
||||
"phpunit/phpunit": "^7.5.20 || ^8.5.2",
|
||||
"psr/http-client": "^1.0",
|
||||
"psr/http-factory": "^1.0",
|
||||
"psr/http-message": "^1.0"
|
||||
},
|
||||
"suggest": {
|
||||
"laminas/laminas-db": "Laminas\\Db component, required by the (No)RecordExists validator",
|
||||
"laminas/laminas-filter": "Laminas\\Filter component, required by the Digits validator",
|
||||
"laminas/laminas-i18n": "Laminas\\I18n component to allow translation of validation error messages",
|
||||
"laminas/laminas-i18n-resources": "Translations of validator messages",
|
||||
"laminas/laminas-math": "Laminas\\Math component, required by the Csrf validator",
|
||||
"laminas/laminas-servicemanager": "Laminas\\ServiceManager component to allow using the ValidatorPluginManager and validator chains",
|
||||
"laminas/laminas-session": "Laminas\\Session component, ^2.8; required by the Csrf validator",
|
||||
"laminas/laminas-uri": "Laminas\\Uri component, required by the Uri and Sitemap\\Loc validators",
|
||||
"psr/http-message": "psr/http-message, required when validating PSR-7 UploadedFileInterface instances via the Upload and UploadFile validators"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laminas": {
|
||||
"component": "Laminas\\Validator",
|
||||
"config-provider": "Laminas\\Validator\\ConfigProvider"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Laminas\\Validator\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria",
|
||||
"homepage": "https://laminas.dev",
|
||||
"keywords": [
|
||||
"laminas",
|
||||
"validator"
|
||||
],
|
||||
"support": {
|
||||
"chat": "https://laminas.dev/chat",
|
||||
"docs": "https://docs.laminas.dev/laminas-validator/",
|
||||
"forum": "https://discourse.laminas.dev",
|
||||
"issues": "https://github.com/laminas/laminas-validator/issues",
|
||||
"rss": "https://github.com/laminas/laminas-validator/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-validator"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2021-01-06T15:05:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "laminas/laminas-zendframework-bridge",
|
||||
"version": "1.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/laminas/laminas-zendframework-bridge.git",
|
||||
"reference": "6ede70583e101030bcace4dcddd648f760ddf642"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/laminas/laminas-zendframework-bridge/zipball/6ede70583e101030bcace4dcddd648f760ddf642",
|
||||
"reference": "6ede70583e101030bcace4dcddd648f760ddf642",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "^5.6 || ^7.0 || ^8.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^5.7 || ^6.5 || ^7.5 || ^8.1 || ^9.3",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laminas": {
|
||||
"module": "Laminas\\ZendFrameworkBridge"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"src/autoload.php"
|
||||
],
|
||||
"psr-4": {
|
||||
"Laminas\\ZendFrameworkBridge\\": "src//"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"BSD-3-Clause"
|
||||
],
|
||||
"description": "Alias legacy ZF class names to Laminas Project equivalents.",
|
||||
"keywords": [
|
||||
"ZendFramework",
|
||||
"autoloading",
|
||||
"laminas",
|
||||
"zf"
|
||||
],
|
||||
"support": {
|
||||
"forum": "https://discourse.laminas.dev/",
|
||||
"issues": "https://github.com/laminas/laminas-zendframework-bridge/issues",
|
||||
"rss": "https://github.com/laminas/laminas-zendframework-bridge/releases.atom",
|
||||
"source": "https://github.com/laminas/laminas-zendframework-bridge"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://funding.communitybridge.org/projects/laminas-project",
|
||||
"type": "community_bridge"
|
||||
}
|
||||
],
|
||||
"time": "2020-09-14T14:23:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "nikic/php-parser",
|
||||
"version": "v4.12.0",
|
||||
@@ -738,60 +1262,6 @@
|
||||
],
|
||||
"time": "2019-12-12T05:00:52+00:00"
|
||||
},
|
||||
{
|
||||
"name": "swiftmailer/swiftmailer",
|
||||
"version": "v5.4.12",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/swiftmailer/swiftmailer.git",
|
||||
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/swiftmailer/swiftmailer/zipball/181b89f18a90f8925ef805f950d47a7190e9b950",
|
||||
"reference": "181b89f18a90f8925ef805f950d47a7190e9b950",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"mockery/mockery": "~0.9.1",
|
||||
"symfony/phpunit-bridge": "~3.2"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "5.4-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"files": [
|
||||
"lib/swift_required.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Chris Corbyn"
|
||||
},
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
}
|
||||
],
|
||||
"description": "Swiftmailer, free feature-rich PHP mailer",
|
||||
"homepage": "https://swiftmailer.symfony.com",
|
||||
"keywords": [
|
||||
"email",
|
||||
"mail",
|
||||
"mailer"
|
||||
],
|
||||
"time": "2018-07-31T09:26:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/cache",
|
||||
"version": "v3.4.47",
|
||||
@@ -2696,6 +3166,56 @@
|
||||
],
|
||||
"time": "2020-10-24T10:57:07+00:00"
|
||||
},
|
||||
{
|
||||
"name": "true/punycode",
|
||||
"version": "v2.1.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/true/php-punycode.git",
|
||||
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/true/php-punycode/zipball/a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
|
||||
"reference": "a4d0c11a36dd7f4e7cd7096076cab6d3378a071e",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=5.3.0",
|
||||
"symfony/polyfill-mbstring": "^1.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.7",
|
||||
"squizlabs/php_codesniffer": "~2.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"TrueBV\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Renan Gonçalves",
|
||||
"email": "renan.saddam@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "A Bootstring encoding of Unicode for Internationalized Domain Names in Applications (IDNA)",
|
||||
"homepage": "https://github.com/true/php-punycode",
|
||||
"keywords": [
|
||||
"idna",
|
||||
"punycode"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/true/php-punycode/issues",
|
||||
"source": "https://github.com/true/php-punycode/tree/master"
|
||||
},
|
||||
"time": "2016-11-16T10:37:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "twig/twig",
|
||||
"version": "v1.42.4",
|
||||
@@ -3007,5 +3527,5 @@
|
||||
"platform-overrides": {
|
||||
"php": "7.1.3"
|
||||
},
|
||||
"plugin-api-version": "2.1.0"
|
||||
"plugin-api-version": "2.2.0"
|
||||
}
|
||||
|
||||
@@ -200,6 +200,17 @@ abstract class ActionNotification extends Action
|
||||
*/
|
||||
class ActionEmail extends ActionNotification
|
||||
{
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.0.1
|
||||
*/
|
||||
const ENUM_HEADER_NAME_MESSAGE_ID = 'Message-ID';
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.0.1
|
||||
*/
|
||||
const ENUM_HEADER_NAME_REFERENCES = 'References';
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@@ -207,13 +218,13 @@ class ActionEmail extends ActionNotification
|
||||
{
|
||||
$aParams = array
|
||||
(
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('name'),
|
||||
"db_table" => "priv_action_email",
|
||||
"db_key_field" => "id",
|
||||
"category" => "grant_by_profile,core/cmdb,application",
|
||||
"key_type" => "autoincrement",
|
||||
"name_attcode" => "name",
|
||||
"state_attcode" => "",
|
||||
"reconc_keys" => array('name'),
|
||||
"db_table" => "priv_action_email",
|
||||
"db_key_field" => "id",
|
||||
"db_finalclass_field" => "",
|
||||
);
|
||||
MetaModel::Init_Params($aParams);
|
||||
@@ -416,9 +427,8 @@ class ActionEmail extends ActionNotification
|
||||
$sBody = MetaModel::ApplyParams($this->Get('body'), $aContextArgs);
|
||||
|
||||
$oObj = $aContextArgs['this->object()'];
|
||||
$sMessageId = sprintf('iTop_%s_%d_%f@%s.openitop.org', get_class($oObj), $oObj->GetKey(), microtime(true /* get as float*/),
|
||||
MetaModel::GetEnvironmentId());
|
||||
$sReference = '<'.$sMessageId.'>';
|
||||
$sMessageId = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_MESSAGE_ID);
|
||||
$sReference = $this->GenerateIdentifierForHeaders($oObj, static::ENUM_HEADER_NAME_REFERENCES);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
@@ -456,8 +466,7 @@ class ActionEmail extends ActionNotification
|
||||
|
||||
$oEmail = new EMail();
|
||||
|
||||
if ($this->IsBeingTested())
|
||||
{
|
||||
if ($this->IsBeingTested()) {
|
||||
$oEmail->SetSubject('TEST['.$sSubject.']');
|
||||
$sTestBody = $sBody;
|
||||
$sTestBody .= "<div style=\"border: dashed;\">\n";
|
||||
@@ -467,8 +476,8 @@ class ActionEmail extends ActionNotification
|
||||
$sTestBody .= "<li>TO: $sTo</li>\n";
|
||||
$sTestBody .= "<li>CC: $sCC</li>\n";
|
||||
$sTestBody .= "<li>BCC: $sBCC</li>\n";
|
||||
$sTestBody .= empty($sFromLabel) ? "<li>From: $sFrom</li>\n": "<li>From: $sFromLabel <$sFrom></li>\n";
|
||||
$sTestBody .= empty($sReplyToLabel) ? "<li>Reply-To: $sReplyTo</li>\n": "<li>Reply-To: $sReplyToLabel <$sReplyTo></li>\n";
|
||||
$sTestBody .= empty($sFromLabel) ? "<li>From: $sFrom</li>\n" : "<li>From: $sFromLabel <$sFrom></li>\n";
|
||||
$sTestBody .= empty($sReplyToLabel) ? "<li>Reply-To: $sReplyTo</li>\n" : "<li>Reply-To: $sReplyToLabel <$sReplyTo></li>\n";
|
||||
$sTestBody .= "<li>References: $sReference</li>\n";
|
||||
$sTestBody .= "</ul>\n";
|
||||
$sTestBody .= "</p>\n";
|
||||
@@ -478,9 +487,9 @@ class ActionEmail extends ActionNotification
|
||||
$oEmail->SetRecipientFrom($sFrom, $sFromLabel);
|
||||
$oEmail->SetReferences($sReference);
|
||||
$oEmail->SetMessageId($sMessageId);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Note: N°4849 We pass the "References" identifier instead of the "Message-ID" on purpose as we want notifications emails to group around the triggering iTop object, not just the users' replies to the notification
|
||||
$oEmail->SetInReplyTo($sReference);
|
||||
} else {
|
||||
$oEmail->SetSubject($sSubject);
|
||||
$oEmail->SetBody($sBody, 'text/html', $sStyles);
|
||||
$oEmail->SetRecipientTO($sTo);
|
||||
@@ -490,6 +499,8 @@ class ActionEmail extends ActionNotification
|
||||
$oEmail->SetRecipientReplyTo($sReplyTo, $sReplyToLabel);
|
||||
$oEmail->SetReferences($sReference);
|
||||
$oEmail->SetMessageId($sMessageId);
|
||||
// Note: N°4849 We pass the "References" identifier instead of the "Message-ID" on purpose as we want notifications emails to group around the triggering iTop object, not just the users' replies to the notification
|
||||
$oEmail->SetInReplyTo($sReference);
|
||||
}
|
||||
|
||||
if (isset($aContextArgs['attachments']))
|
||||
@@ -516,26 +527,64 @@ class ActionEmail extends ActionNotification
|
||||
{
|
||||
case EMAIL_SEND_OK:
|
||||
return "Sent";
|
||||
|
||||
|
||||
case EMAIL_SEND_PENDING:
|
||||
return "Pending";
|
||||
|
||||
|
||||
case EMAIL_SEND_ERROR:
|
||||
return "Errors: ".implode(', ', $aErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (is_array($this->m_aMailErrors) && count($this->m_aMailErrors) > 0)
|
||||
{
|
||||
} else {
|
||||
if (is_array($this->m_aMailErrors) && count($this->m_aMailErrors) > 0) {
|
||||
$sError = implode(', ', $this->m_aMailErrors);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
$sError = 'Unknown reason';
|
||||
}
|
||||
|
||||
return 'Notification was not sent: '.$sError;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param \DBObject $oObject
|
||||
* @param string $sHeaderName {@see \ActionEmail::ENUM_HEADER_NAME_REFERENCES}, {@see \ActionEmail::ENUM_HEADER_NAME_MESSAGE_ID}
|
||||
*
|
||||
* @return string The formatted identifier for $sHeaderName based on $oObject
|
||||
* @throws \Exception
|
||||
* @since 3.0.1 N°4849
|
||||
*/
|
||||
protected function GenerateIdentifierForHeaders(DBObject $oObject, string $sHeaderName): string
|
||||
{
|
||||
$sObjClass = get_class($oObject);
|
||||
$sObjId = $oObject->GetKey();
|
||||
$sAppName = utils::Sanitize(ITOP_APPLICATION_SHORT, '', utils::ENUM_SANITIZATION_FILTER_VARIABLE_NAME);
|
||||
|
||||
switch ($sHeaderName) {
|
||||
case static::ENUM_HEADER_NAME_MESSAGE_ID:
|
||||
case static::ENUM_HEADER_NAME_REFERENCES:
|
||||
// Prefix
|
||||
$sPrefix = sprintf('%s_%s_%d', $sAppName, $sObjClass, $sObjId);
|
||||
if ($sHeaderName === static::ENUM_HEADER_NAME_MESSAGE_ID) {
|
||||
$sPrefix .= sprintf('_%f', microtime(true /* get as float*/));
|
||||
}
|
||||
// Suffix
|
||||
$sSuffix = sprintf('@%s.openitop.org', MetaModel::GetEnvironmentId());
|
||||
// Identifier
|
||||
$sIdentifier = $sPrefix.$sSuffix;
|
||||
if ($sHeaderName === static::ENUM_HEADER_NAME_REFERENCES) {
|
||||
$sIdentifier = "<$sIdentifier>";
|
||||
}
|
||||
|
||||
return $sIdentifier;
|
||||
}
|
||||
|
||||
// Requested header name invalid
|
||||
$sErrorMessage = sprintf('%s: Could not generate identifier for header "%s", only %s are supported', static::class, $sHeaderName, implode(' / ', [static::ENUM_HEADER_NAME_MESSAGE_ID, static::ENUM_HEADER_NAME_REFERENCES]));
|
||||
IssueLog::Error($sErrorMessage, LogChannels::NOTIFICATIONS, [
|
||||
'Object' => $sObjClass.'::'.$sObjId.' ('.$oObject->GetRawName().')',
|
||||
'Action' => get_class($this).'::'.$this->GetKey().' ('.$this->GetRawName().')',
|
||||
]);
|
||||
throw new Exception($sErrorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,8 +409,6 @@ class AsyncSendEmail extends AsyncTask
|
||||
$oNew->Set('to', $oEMail->GetRecipientTO(true /* string */));
|
||||
$oNew->Set('subject', $oEMail->GetSubject());
|
||||
|
||||
// $oNew->Set('version', 1);
|
||||
// $sMessage = serialize($oEMail);
|
||||
$oNew->Set('version', 2);
|
||||
$sMessage = $oEMail->SerializeV2();
|
||||
$oNew->Set('message', $sMessage);
|
||||
|
||||
@@ -78,23 +78,31 @@ class CMDBChangeOp extends DBObject implements iCMDBChangeOp
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
* Describe (as a text string) the modifications corresponding to this change
|
||||
*/
|
||||
public function GetDescription()
|
||||
{
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Safety net: in case the change is not given, let's guarantee that it will
|
||||
* be set to the current ongoing change (or create a new one)
|
||||
*/
|
||||
* Safety net:
|
||||
* * if change isn't persisted yet, use the current change and persist it if needed
|
||||
* * in case the change is not given, let's guarantee that it will be set to the current ongoing change (or create a new one)
|
||||
*
|
||||
* @since 2.7.7 3.0.2 3.1.0 N°3717 do persist the current change if needed
|
||||
*/
|
||||
protected function OnInsert()
|
||||
{
|
||||
if ($this->Get('change') <= 0)
|
||||
{
|
||||
$this->Set('change', CMDBObject::GetCurrentChange());
|
||||
$iChange = $this->Get('change');
|
||||
if (($iChange <= 0) || (is_null($iChange))) {
|
||||
$oChange = CMDBObject::GetCurrentChange();
|
||||
if ($oChange->IsNew()) {
|
||||
$oChange->DBWrite();
|
||||
}
|
||||
$this->Set('change', $oChange);
|
||||
}
|
||||
|
||||
parent::OnInsert();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,6 +113,26 @@ abstract class CMDBObject extends DBObject
|
||||
self::$m_oCurrChange = $oChange;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $sUserInfo
|
||||
* @param string $sOrigin
|
||||
* @param \DateTime $oDate
|
||||
*
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @since 2.7.7 3.0.2 3.1.0 N°3717 new method to reset current change
|
||||
*/
|
||||
public static function SetCurrentChangeFromParams($sUserInfo, $sOrigin = null, $oDate = null)
|
||||
{
|
||||
static::SetTrackInfo($sUserInfo);
|
||||
static::SetTrackOrigin($sOrigin);
|
||||
static::CreateChange();
|
||||
|
||||
if (!is_null($oDate)) {
|
||||
static::$m_oCurrChange->Set("date", $oDate);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Todo: simplify the APIs and do not pass the current change as an argument anymore
|
||||
// SetTrackInfo to be invoked in very few cases (UI.php, CSV import, Data synchro)
|
||||
@@ -144,6 +164,8 @@ abstract class CMDBObject extends DBObject
|
||||
* $oMyChange->Set("userinfo", 'this is done by ... for ...');
|
||||
* $iChangeId = $oMyChange->DBInsert();
|
||||
*
|
||||
* **warning** : this will do nothing if current change already exists !
|
||||
*
|
||||
* @see SetCurrentChange to specify a CMDBObject instance instead
|
||||
*
|
||||
* @param string $sInfo
|
||||
@@ -171,6 +193,8 @@ abstract class CMDBObject extends DBObject
|
||||
/**
|
||||
* Provides information about the origin of the change
|
||||
*
|
||||
* **warning** : this will do nothing if current change already exists !
|
||||
*
|
||||
* @see SetTrackInfo
|
||||
* @see SetCurrentChange to specify a CMDBObject instance instead
|
||||
*
|
||||
@@ -181,18 +205,15 @@ abstract class CMDBObject extends DBObject
|
||||
{
|
||||
self::$m_sOrigin = $sOrigin;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the additional information (defaulting to user name)
|
||||
*/
|
||||
protected static function GetTrackInfo()
|
||||
*/
|
||||
public static function GetTrackInfo()
|
||||
{
|
||||
if (is_null(self::$m_sInfo))
|
||||
{
|
||||
if (is_null(self::$m_sInfo)) {
|
||||
return CMDBChange::GetCurrentUserName();
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
return self::$m_sInfo;
|
||||
}
|
||||
}
|
||||
@@ -243,6 +264,9 @@ abstract class CMDBObject extends DBObject
|
||||
* @throws \CoreWarning
|
||||
* @throws \MySQLException
|
||||
* @throws \OQLException
|
||||
*
|
||||
* @since 2.7.7 3.0.2 3.1.0 N°3717 {@see CMDBChange} **will be persisted later** in {@see \CMDBChangeOp::OnInsert} (was done previously directly here)
|
||||
* This will avoid creating in DB CMDBChange lines without any corresponding CMDBChangeOp
|
||||
*/
|
||||
protected static function CreateChange()
|
||||
{
|
||||
@@ -251,7 +275,6 @@ abstract class CMDBObject extends DBObject
|
||||
self::$m_oCurrChange->Set("userinfo", self::GetTrackInfo());
|
||||
self::$m_oCurrChange->Set("user_id", self::GetTrackUserId());
|
||||
self::$m_oCurrChange->Set("origin", self::GetTrackOrigin());
|
||||
self::$m_oCurrChange->DBInsert();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -351,19 +351,21 @@ class CMDBSource
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the version of the database server.
|
||||
*
|
||||
* @return string
|
||||
* @throws \MySQLException
|
||||
*
|
||||
* @uses \CMDBSource::QueryToCol() so needs a connection opened !
|
||||
* @uses \CMDBSource::QueryToScalar() so needs a connection opened !
|
||||
*/
|
||||
public static function GetDBVersion()
|
||||
{
|
||||
$aVersions = self::QueryToCol('SELECT Version() as version', 'version');
|
||||
return $aVersions[0];
|
||||
return static::QueryToScalar('SELECT VERSION()', 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @deprecated Use `CMDBSource::GetDBVersion` instead.
|
||||
* @uses mysqli_get_server_info
|
||||
*/
|
||||
public static function GetServerInfo()
|
||||
{
|
||||
@@ -1499,20 +1501,14 @@ class CMDBSource
|
||||
* Returns the value of the specified server variable
|
||||
* @param string $sVarName Name of the server variable
|
||||
* @return mixed Current value of the variable
|
||||
*/
|
||||
* @throws \MySQLQueryHasNoResultException|\MySQLException
|
||||
*/
|
||||
public static function GetServerVariable($sVarName)
|
||||
{
|
||||
$result = '';
|
||||
$sSql = "SELECT @@$sVarName as theVar";
|
||||
$aRows = self::QueryToArray($sSql);
|
||||
if (count($aRows) > 0)
|
||||
{
|
||||
$result = $aRows[0]['theVar'];
|
||||
}
|
||||
return $result;
|
||||
$sSql = 'SELECT @@'.$sVarName;
|
||||
return static::QueryToScalar($sSql, 0) ?: '';
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the privileges of the current user
|
||||
* @return string privileges in a raw format
|
||||
|
||||
@@ -29,7 +29,7 @@ define('ITOP_APPLICATION_SHORT', 'iTop');
|
||||
*
|
||||
* @see ITOP_CORE_VERSION to get iTop core version
|
||||
*/
|
||||
define('ITOP_VERSION', '3.0.1-dev');
|
||||
define('ITOP_VERSION', '3.1.0-dev');
|
||||
|
||||
define('ITOP_VERSION_NAME', 'Fullmoon');
|
||||
define('ITOP_REVISION', 'svn');
|
||||
@@ -489,13 +489,21 @@ class Config
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'cron_max_execution_time' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Duration (seconds) of the page cron.php, must be shorter than php setting max_execution_time and shorter than the web server response timeout',
|
||||
'default' => 600,
|
||||
'value' => 600,
|
||||
'source_of_value' => '',
|
||||
'type' => 'integer',
|
||||
'description' => 'Duration (seconds) of the cron.php script : if exceeded the script will exit even if there are remaining tasks to process. Must be shorter than php max_execution_time setting (note than when using CLI, this is set to 0 by default which means unlimited). If cron.php is ran via web, it must be shorter than the web server response timeout.',
|
||||
'default' => 600,
|
||||
'value' => 600,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
],
|
||||
'cron_task_max_execution_time' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Background tasks will use this value (integer) multiplicated by its periodicity (in seconds) as max duration per cron execution. 0 is unlimited time',
|
||||
'default' => 0,
|
||||
'value' => 0,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'cron_sleep' => [
|
||||
'type' => 'integer',
|
||||
'description' => 'Duration (seconds) before cron.php checks again if something must be done',
|
||||
@@ -878,7 +886,7 @@ class Config
|
||||
'type' => 'string',
|
||||
'description' => 'Regular expression to validate/detect the format of an URL (URL attributes and Wiki formatting for Text attributes)',
|
||||
'default' => /** @lang RegExp */
|
||||
'(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9:%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)?',
|
||||
'(https?|ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9:%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z0-9_.-][a-zA-Z0-9+\$_.-]*)?',
|
||||
// SCHEME....... USER....................... PASSWORD.......................... HOST/IP........... PORT.......... PATH......................... GET............................................ ANCHOR..........................
|
||||
// Example: http://User:passWord@127.0.0.1:8888/patH/Page.php?arrayArgument[2]=something:blah20#myAnchor
|
||||
// RegExp source: http://www.php.net/manual/fr/function.preg-match.php#93824
|
||||
@@ -1544,6 +1552,14 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
'setup.launch_button.enabled' => [
|
||||
'type' => 'bool',
|
||||
'description' => 'If true displays in the Application Upgrade screen a button allowing to launch the setup in a single click (no more manual config file permission change needed)',
|
||||
'default' => null,
|
||||
'value' => false,
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => false,
|
||||
],
|
||||
];
|
||||
|
||||
public function IsProperty($sPropCode)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<user_rights>
|
||||
<profiles>
|
||||
<profile id="1024" _delta="define">
|
||||
|
||||
@@ -1732,6 +1732,7 @@ abstract class DBObject implements iDisplay
|
||||
$iFlags = 0; // By default (if no life cycle) no flag at all
|
||||
$sClass = get_class($this);
|
||||
|
||||
// The code below prevents to hide a DashboardAttribute for eg.
|
||||
$aReadOnlyAtts = $this->GetReadOnlyAttributes();
|
||||
if (($aReadOnlyAtts != null) && (in_array($sAttCode, $aReadOnlyAtts)))
|
||||
{
|
||||
@@ -3413,6 +3414,54 @@ abstract class DBObject implements iDisplay
|
||||
return $this->m_iKey;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increment attribute with specified value.
|
||||
* This function is only applicable with AttributeInteger.
|
||||
*
|
||||
* @api
|
||||
*
|
||||
* @param string $sAttCode attribute code
|
||||
* @param int $iValue value to increment (default value 1)
|
||||
*
|
||||
* @return int incremented value
|
||||
*
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*/
|
||||
public function DBIncrement(string $sAttCode, int $iValue = 1)
|
||||
{
|
||||
// retrieve instance class
|
||||
$sClass = get_class($this);
|
||||
|
||||
// dirty object not allowed
|
||||
if($this->m_bDirty){
|
||||
throw new CoreException("Invalid DBIncrement usage, dirty objects are not allowed. Call DBUpdate before calling DBIncrement.");
|
||||
}
|
||||
|
||||
// ensure attribute type is AttributeInteger
|
||||
$oAttr = MetaModel::GetAttributeDef($sClass, $sAttCode);
|
||||
if(!$oAttr instanceof AttributeInteger){
|
||||
throw new CoreException(sprintf("Invalid DBIncrement usage, attribute type of {$sAttCode} is %s. Only AttributeInteger are compatibles with DBIncrement.", get_class($oAttr)));
|
||||
}
|
||||
|
||||
// prepare SQL statement
|
||||
$sTable = MetaModel::DBGetTable($sClass, $sAttCode);
|
||||
$sPKField = '`'.MetaModel::DBGetKey($sClass).'`';
|
||||
$sKey = CMDBSource::Quote($this->m_iKey);
|
||||
$sUpdateSQL = "UPDATE `{$sTable}` SET `{$sAttCode}` = `{$sAttCode}`+{$iValue} WHERE {$sPKField} = {$sKey}";
|
||||
|
||||
// execute SQL query
|
||||
CMDBSource::Query($sUpdateSQL);
|
||||
|
||||
// reload instance with new value
|
||||
$this->Reload();
|
||||
|
||||
return $this->Get($sAttCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate TriggerOnObjectMention triggers for the current object
|
||||
*
|
||||
@@ -4386,14 +4435,22 @@ abstract class DBObject implements iDisplay
|
||||
$sAttCode = $sPlaceholderAttCode;
|
||||
}
|
||||
|
||||
if ($sVerb == 'hyperlink')
|
||||
if (in_array($sVerb, ['hyperlink', 'url']))
|
||||
{
|
||||
$sPortalId = ($sAttCode === '') ? 'console' : $sAttCode;
|
||||
if (!array_key_exists($sPortalId, self::$aPortalToURLMaker))
|
||||
{
|
||||
throw new Exception("Unknown portal id '$sPortalId' in placeholder '$sPlaceholderAttCode''");
|
||||
}
|
||||
$ret = $this->GetHyperlink(self::$aPortalToURLMaker[$sPortalId], false);
|
||||
|
||||
if($sVerb == 'hyperlink')
|
||||
{
|
||||
$ret = $this->GetHyperlink(self::$aPortalToURLMaker[$sPortalId], false);
|
||||
}
|
||||
else
|
||||
{
|
||||
$ret = ApplicationContext::MakeObjectUrl(get_class($this), $this->GetKey(), self::$aPortalToURLMaker[$sPortalId], false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -413,6 +413,10 @@ class DBObjectSearch extends DBSearch
|
||||
}
|
||||
|
||||
/**
|
||||
* Important: If you need to add a condition on the same $sFilterCode several times with different $value values; do not use this method as the previous $value occurences will be replaced by the last. Instead use:
|
||||
* * {@see \DBObjectSearch::AddConditionExpression()} in loops to add conditions one by one
|
||||
* * {@see \DBObjectSearch::AddConditionForInOperatorUsingParam()} for IN/NOT IN queries with lots of params at once
|
||||
*
|
||||
* @param string $sFilterCode
|
||||
* @param mixed $value
|
||||
* @param string $sOpCode operator to use : 'IN', 'NOT IN', 'Contains',' Begins with', 'Finishes with', ...
|
||||
@@ -423,8 +427,6 @@ class DBObjectSearch extends DBSearch
|
||||
* @param bool $bParseSearchString
|
||||
*
|
||||
* @throws \CoreException
|
||||
*
|
||||
* @see AddConditionForInOperatorUsingParam for IN/NOT IN queries with lots of params
|
||||
*/
|
||||
public function AddCondition($sFilterCode, $value, $sOpCode = null, $bParseSearchString = false)
|
||||
{
|
||||
|
||||
@@ -1421,13 +1421,14 @@ class DisplayableGraph extends SimpleGraph
|
||||
* @param int $iObjKey
|
||||
* @param string $sContextKey
|
||||
* @param array $aContextParams
|
||||
* @param bool $bLazyLoading since 2.7.7 3.0.1
|
||||
*
|
||||
* @throws \CoreException
|
||||
* @throws \DictExceptionMissingString
|
||||
*/
|
||||
function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams = array(), bool $sLazyLoading = false)
|
||||
function Display(WebPage $oP, $aResults, $sRelation, ApplicationContext $oAppContext, $aExcludedObjects, $sObjClass, $iObjKey, $sContextKey, $aContextParams = array(), bool $bLazyLoading = false)
|
||||
{
|
||||
list($aExcludedByClass, $aAdditionalContexts) = $this->DisplayFiltering($sContextKey, $aContextParams, $aExcludedObjects, $oP, $aResults, $sLazyLoading);
|
||||
list($aExcludedByClass, $aAdditionalContexts) = $this->DisplayFiltering($sContextKey, $aContextParams, $aExcludedObjects, $oP, $aResults, $bLazyLoading);
|
||||
|
||||
$iGroupingThreshold = utils::ReadParam('g', 5);
|
||||
|
||||
@@ -1508,10 +1509,12 @@ class DisplayableGraph extends SimpleGraph
|
||||
// Export as Attachment requires GD (for building the PDF) AND a valid objclass/objkey couple
|
||||
unset($aParams['export_as_attachment']);
|
||||
}
|
||||
if ($oP->IsPrintableVersion() || !$sLazyLoading) {
|
||||
if ($oP->IsPrintableVersion() || !$bLazyLoading) {
|
||||
$oP->add_ready_script(" $('#$sId').simple_graph(".json_encode($aParams).");");
|
||||
} else {
|
||||
$oP->add_script("function Load(){var aExcluded = []; $('input[name^=excluded]').each( function() {if (!$(this).prop('checked')) { aExcluded.push($(this).val()); }} ); var params= $.extend(".json_encode($aParams).", {excluded_classes: aExcluded}); $('#$sId').simple_graph(params);}");
|
||||
$oP->add_ready_script("$('#impacted_objects_lists').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');$('#impacted_groups').html('".utils::TextToHtml(Dict::S('Relation:impacts/NoFilteredData'))."');");
|
||||
|
||||
}
|
||||
}
|
||||
catch(Exception $e)
|
||||
@@ -1551,6 +1554,7 @@ EOF
|
||||
* @param array $aExcludedObjects
|
||||
* @param \WebPage $oP
|
||||
* @param array $aResults
|
||||
* @param bool $bLazyLoading
|
||||
*
|
||||
* @return array
|
||||
* @throws \CoreException
|
||||
@@ -1560,7 +1564,7 @@ EOF
|
||||
* @throws \Twig\Error\RuntimeError
|
||||
* @throws \Twig\Error\SyntaxError
|
||||
*/
|
||||
public function DisplayFiltering(string $sContextKey, array $aContextParams, array $aExcludedObjects, WebPage $oP, array $aResults, bool $sLazyLoading = false): array
|
||||
public function DisplayFiltering(string $sContextKey, array $aContextParams, array $aExcludedObjects, WebPage $oP, array $aResults, bool $bLazyLoading = false): array
|
||||
{
|
||||
$aContextDefs = static::GetContextDefinitions($sContextKey, true, $aContextParams);
|
||||
$aExcludedByClass = array();
|
||||
@@ -1590,7 +1594,7 @@ EOF
|
||||
$("#ReloadMovieBtn").button().button("disable");
|
||||
EOF
|
||||
);
|
||||
if ($sLazyLoading) {
|
||||
if ($bLazyLoading) {
|
||||
$oP->add_ready_script("$('#ReloadMovieBtn').button('enable');");
|
||||
} else {
|
||||
$oP->add_ready_script("$('#dh_flash').addClass('closed');");
|
||||
@@ -1614,7 +1618,7 @@ EOF
|
||||
$idx++;
|
||||
}
|
||||
$oUiHtmlBlock->AddHtml("</div>");
|
||||
if ($sLazyLoading) {
|
||||
if ($bLazyLoading) {
|
||||
$sOnCLick = "Load(); $('#ReloadMovieBtn').attr('onclick','DoReload()');$('#ReloadMovieBtn').html('".Dict::S('UI:Button:Refresh')."');";
|
||||
$oUiHtmlBlock->AddHtml("<button type=\"button\" id=\"ReloadMovieBtn\" class=\"ibo-button ibo-is-neutral ibo-is-regular\" onClick=\"$sOnCLick\">".Dict::S('Relation:impacts/LoadData')."</button></div></form>");
|
||||
} else {
|
||||
|
||||
@@ -24,13 +24,18 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
use Laminas\Mail\Header\ContentType;
|
||||
use Laminas\Mail\Message;
|
||||
use Laminas\Mail\Transport\File;
|
||||
use Laminas\Mail\Transport\FileOptions;
|
||||
use Laminas\Mail\Transport\SmtpOptions;
|
||||
use Laminas\Mail\Transport\Smtp;
|
||||
use Laminas\Mime\Mime;
|
||||
use Laminas\Mime\Part;
|
||||
use Pelago\Emogrifier\CssInliner;
|
||||
use Pelago\Emogrifier\HtmlProcessor\CssToAttributeConverter;
|
||||
use Pelago\Emogrifier\HtmlProcessor\HtmlPruner;
|
||||
|
||||
Swift_Preferences::getInstance()->setCharset('UTF-8');
|
||||
|
||||
|
||||
define ('EMAIL_SEND_OK', 0);
|
||||
define ('EMAIL_SEND_PENDING', 1);
|
||||
define ('EMAIL_SEND_ERROR', 2);
|
||||
@@ -58,7 +63,8 @@ class EMail
|
||||
public function __construct()
|
||||
{
|
||||
$this->m_aData = array();
|
||||
$this->m_oMessage = Swift_Message::newInstance();
|
||||
$this->m_oMessage = new Message();
|
||||
$this->m_oMessage->setEncoding('UTF-8');
|
||||
$this->SetRecipientFrom(MetaModel::GetConfig()->Get('email_default_sender_address'), MetaModel::GetConfig()->Get('email_default_sender_label'));
|
||||
}
|
||||
|
||||
@@ -72,12 +78,18 @@ class EMail
|
||||
{
|
||||
return serialize($this->m_aData);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Custom de-serialization method
|
||||
*
|
||||
* @param string $sSerializedMessage The serialized representation of the message
|
||||
*
|
||||
* @return \EMail
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
|
||||
*/
|
||||
static public function UnSerializeV2($sSerializedMessage)
|
||||
public static function UnSerializeV2($sSerializedMessage)
|
||||
{
|
||||
$aData = unserialize($sSerializedMessage);
|
||||
$oMessage = new Email();
|
||||
@@ -115,7 +127,6 @@ class EMail
|
||||
$oMessage->SetSubject($aData['subject']);
|
||||
}
|
||||
|
||||
|
||||
if (array_key_exists('headers', $aData))
|
||||
{
|
||||
foreach($aData['headers'] as $sKey => $sValue)
|
||||
@@ -155,10 +166,11 @@ class EMail
|
||||
return EMAIL_SEND_PENDING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \Exception
|
||||
*/
|
||||
protected function SendSynchronous(&$aIssues, $oLog = null)
|
||||
{
|
||||
// If the body of the message is in HTML, embed all images based on attachments
|
||||
$this->EmbedInlineImages();
|
||||
|
||||
$this->LoadConfig();
|
||||
|
||||
@@ -172,50 +184,54 @@ class EMail
|
||||
$sUserName = self::$m_oConfig->Get('email_transport_smtp.username');
|
||||
$sPassword = self::$m_oConfig->Get('email_transport_smtp.password');
|
||||
|
||||
$oTransport = Swift_SmtpTransport::newInstance($sHost, $sPort, $sEncryption);
|
||||
$oTransport = new Smtp();
|
||||
$aOptions= [
|
||||
'host' => $sHost,
|
||||
'port' => $sPort,
|
||||
'connection_class' => 'login',
|
||||
'connection_config' => [
|
||||
'ssl' => $sEncryption,
|
||||
],
|
||||
];
|
||||
if (strlen($sUserName) > 0)
|
||||
{
|
||||
$oTransport->setUsername($sUserName);
|
||||
$oTransport->setPassword($sPassword);
|
||||
$aOptions['connection_config']['username'] = $sUserName;
|
||||
$aOptions['connection_config']['password'] = $sPassword;
|
||||
}
|
||||
$oOptions = new SmtpOptions($aOptions);
|
||||
$oTransport->setOptions($oOptions);
|
||||
break;
|
||||
|
||||
case 'Null':
|
||||
$oTransport = Swift_NullTransport::newInstance();
|
||||
$oTransport = new Smtp();
|
||||
break;
|
||||
|
||||
case 'LogFile':
|
||||
$oTransport = Swift_LogFileTransport::newInstance();
|
||||
$oTransport->setLogFile(APPROOT.'log/mail.log');
|
||||
$oTransport = new File();
|
||||
$aOptions = new FileOptions([
|
||||
'path' => APPROOT.'log/mail.log',
|
||||
]);
|
||||
$oTransport->setOptions($aOptions);
|
||||
break;
|
||||
|
||||
case 'PHPMail':
|
||||
default:
|
||||
$oTransport = Swift_MailTransport::newInstance();
|
||||
$oTransport = new Smtp();
|
||||
}
|
||||
|
||||
$oMailer = Swift_Mailer::newInstance($oTransport);
|
||||
|
||||
$aFailedRecipients = array();
|
||||
$this->m_oMessage->setMaxLineLength(0);
|
||||
|
||||
$oKPI = new ExecutionKPI();
|
||||
try
|
||||
{
|
||||
$iSent = $oMailer->send($this->m_oMessage, $aFailedRecipients);
|
||||
if ($iSent === 0)
|
||||
{
|
||||
// Beware: it seems that $aFailedRecipients sometimes contains the recipients that actually received the message !!!
|
||||
IssueLog::Warning('Email sending failed: Some recipients were invalid, aFailedRecipients contains: '.implode(', ', $aFailedRecipients));
|
||||
$aIssues = array('Some recipients were invalid.');
|
||||
$oKPI->ComputeStats('Email Sent', 'Error received');
|
||||
return EMAIL_SEND_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
$aIssues = array();
|
||||
$oKPI->ComputeStats('Email Sent', 'Succeded');
|
||||
return EMAIL_SEND_OK;
|
||||
}
|
||||
$oTransport->send($this->m_oMessage);
|
||||
$aIssues = array();
|
||||
$oKPI->ComputeStats('Email Sent', 'Succeded');
|
||||
return EMAIL_SEND_OK;
|
||||
}
|
||||
catch(Laminas\Mail\Transport\Exception\RuntimeException $e){
|
||||
IssueLog::Warning('Email sending failed: Some recipients were invalid');
|
||||
$aIssues = array('Some recipients were invalid.');
|
||||
$oKPI->ComputeStats('Email Sent', 'Error received');
|
||||
return EMAIL_SEND_ERROR;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
@@ -223,51 +239,65 @@ class EMail
|
||||
throw $e;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reprocess the body of the message (if it is an HTML message)
|
||||
* to replace the URL of images based on attachments by a link
|
||||
* to an embedded image (i.e. cid:....)
|
||||
* to an embedded image (i.e. cid:....) and returns images to be attached as an array
|
||||
*
|
||||
* @param string $sBody Email body to process/alter
|
||||
*
|
||||
* @return array Array of Part that needs to be added as inline attachment later to render as embed
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
*/
|
||||
protected function EmbedInlineImages()
|
||||
protected function EmbedInlineImages(string &$sBody)
|
||||
{
|
||||
if ($this->m_aData['body']['mimeType'] == 'text/html')
|
||||
$oDOMDoc = new DOMDocument();
|
||||
$oDOMDoc->preserveWhitespace = true;
|
||||
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$sBody); // For loading HTML chunks where the character set is not specified
|
||||
|
||||
$oXPath = new DOMXPath($oDOMDoc);
|
||||
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
|
||||
$oImagesList = $oXPath->query($sXPath);
|
||||
$oImagesContent = new \Laminas\Mime\Message();
|
||||
$aImagesParts = [];
|
||||
if ($oImagesList->length != 0)
|
||||
{
|
||||
$oDOMDoc = new DOMDocument();
|
||||
$oDOMDoc->preserveWhitespace = true;
|
||||
@$oDOMDoc->loadHTML('<?xml encoding="UTF-8"?>'.$this->m_aData['body']['body']); // For loading HTML chunks where the character set is not specified
|
||||
|
||||
$oXPath = new DOMXPath($oDOMDoc);
|
||||
$sXPath = '//img[@'.InlineImage::DOM_ATTR_ID.']';
|
||||
$oImagesList = $oXPath->query($sXPath);
|
||||
|
||||
if ($oImagesList->length != 0)
|
||||
foreach($oImagesList as $oImg)
|
||||
{
|
||||
foreach($oImagesList as $oImg)
|
||||
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
|
||||
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
|
||||
if ($oAttachment)
|
||||
{
|
||||
$iAttId = $oImg->getAttribute(InlineImage::DOM_ATTR_ID);
|
||||
$oAttachment = MetaModel::GetObject('InlineImage', $iAttId, false, true /* Allow All Data */);
|
||||
if ($oAttachment)
|
||||
$sImageSecret = $oImg->getAttribute('data-img-secret');
|
||||
$sAttachmentSecret = $oAttachment->Get('secret');
|
||||
if ($sImageSecret !== $sAttachmentSecret)
|
||||
{
|
||||
$sImageSecret = $oImg->getAttribute('data-img-secret');
|
||||
$sAttachmentSecret = $oAttachment->Get('secret');
|
||||
if ($sImageSecret !== $sAttachmentSecret)
|
||||
{
|
||||
// @see N°1921
|
||||
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
|
||||
continue;
|
||||
}
|
||||
|
||||
$oDoc = $oAttachment->Get('contents');
|
||||
$oSwiftImage = new Swift_Image($oDoc->GetData(), $oDoc->GetFileName(), $oDoc->GetMimeType());
|
||||
$sCid = $this->m_oMessage->embed($oSwiftImage);
|
||||
$oImg->setAttribute('src', $sCid);
|
||||
// @see N°1921
|
||||
// If copying from another iTop we could get an IMG pointing to an InlineImage with wrong secret
|
||||
continue;
|
||||
}
|
||||
|
||||
$oDoc = $oAttachment->Get('contents');
|
||||
|
||||
$sCid = uniqid('', true);
|
||||
|
||||
$oNewAttachment = new Part($oDoc->GetData());
|
||||
$oNewAttachment->id = $sCid;
|
||||
$oNewAttachment->type = $oDoc->GetMimeType();
|
||||
$oNewAttachment->filename = $oDoc->GetFileName();
|
||||
$oNewAttachment->disposition = Mime::DISPOSITION_INLINE;
|
||||
$oNewAttachment->encoding = Mime::ENCODING_BASE64;
|
||||
|
||||
$oImagesContent->addPart($oNewAttachment);
|
||||
$oImg->setAttribute('src', 'cid:'.$sCid);
|
||||
$aImagesParts[] = $oNewAttachment;
|
||||
}
|
||||
}
|
||||
$sHtmlBody = $oDOMDoc->saveHTML();
|
||||
$this->m_oMessage->setBody($sHtmlBody, 'text/html', 'UTF-8');
|
||||
}
|
||||
$sBody = $oDOMDoc->saveHTML();
|
||||
return $aImagesParts;
|
||||
}
|
||||
|
||||
public function Send(&$aIssues, $bForceSynchronous = false, $oLog = null)
|
||||
@@ -313,7 +343,7 @@ class EMail
|
||||
break;
|
||||
|
||||
default:
|
||||
$oHeaders->addTextHeader($sKey, $sValue);
|
||||
$oHeaders->addHeaderLine($sKey, $sValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -325,46 +355,146 @@ class EMail
|
||||
// Note: Swift will add the angle brackets for you
|
||||
// so let's remove the angle brackets if present, for historical reasons
|
||||
$sId = str_replace(array('<', '>'), '', $sId);
|
||||
|
||||
$oMsgId = $this->m_oMessage->getHeaders()->get('Message-ID');
|
||||
$oMsgId->SetId($sId);
|
||||
|
||||
$this->m_oMessage->getHeaders()->addHeaderLine('Message-ID', $sId);
|
||||
}
|
||||
|
||||
|
||||
public function SetReferences($sReferences)
|
||||
{
|
||||
$this->AddToHeader('References', $sReferences);
|
||||
}
|
||||
|
||||
public function SetBody($sBody, $sMimeType = 'text/html', $sCustomStyles = null)
|
||||
/**
|
||||
* Set the "In-Reply-To" header to allow emails to group as a conversation in modern mail clients (GMail, Outlook 2016+, ...)
|
||||
*
|
||||
* @link https://en.wikipedia.org/wiki/Email#Header_fields
|
||||
*
|
||||
* @param string $sMessageId
|
||||
*
|
||||
* @since 3.0.1 N°4849
|
||||
*/
|
||||
public function SetInReplyTo(string $sMessageId)
|
||||
{
|
||||
if (($sMimeType === 'text/html') && ($sCustomStyles !== null))
|
||||
{
|
||||
$this->AddToHeader('In-Reply-To', $sMessageId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set current Email body and process inline images.
|
||||
*
|
||||
* @param $sBody
|
||||
* @param string $sMimeType
|
||||
* @param $sCustomStyles
|
||||
*
|
||||
* @return void
|
||||
* @throws \ArchivedObjectException
|
||||
* @throws \CoreException
|
||||
* @throws \Symfony\Component\CssSelector\Exception\SyntaxErrorException
|
||||
*/
|
||||
public function SetBody($sBody, string $sMimeType = Mime::TYPE_HTML, $sCustomStyles = null)
|
||||
{
|
||||
$oBody = new Laminas\Mime\Message();
|
||||
$aAdditionalParts = [];
|
||||
|
||||
if (($sMimeType === Mime::TYPE_HTML) && ($sCustomStyles !== null)) {
|
||||
$oDomDocument = CssInliner::fromHtml($sBody)->inlineCss($sCustomStyles)->getDomDocument();
|
||||
HtmlPruner::fromDomDocument($oDomDocument)->removeElementsWithDisplayNone();
|
||||
$sBody = CssToAttributeConverter::fromDomDocument($oDomDocument)->convertCssToVisualAttributes()->render(); // Adds html/body tags if not already present
|
||||
}
|
||||
$this->m_aData['body'] = array('body' => $sBody, 'mimeType' => $sMimeType);
|
||||
$this->m_oMessage->setBody($sBody, $sMimeType);
|
||||
|
||||
// We don't want these modifications in m_aData['body'], otherwise it'll ruin asynchronous mail as they go through this method twice
|
||||
if ($sMimeType === Mime::TYPE_HTML){
|
||||
$aAdditionalParts = $this->EmbedInlineImages($sBody);
|
||||
}
|
||||
|
||||
// Add body content to as a new part
|
||||
$oNewPart = new Part($sBody);
|
||||
$oNewPart->encoding = Mime::ENCODING_8BIT;
|
||||
$oNewPart->type = $sMimeType;
|
||||
$oBody->addPart($oNewPart);
|
||||
|
||||
// Add additional images as new body parts
|
||||
foreach ($aAdditionalParts as $oAdditionalPart) {
|
||||
$oBody->addPart($oAdditionalPart);
|
||||
}
|
||||
|
||||
if($oBody->isMultiPart()){
|
||||
$oContentTypeHeader = $this->m_oMessage->getHeaders();
|
||||
foreach ($oContentTypeHeader as $oHeader) {
|
||||
if (!$oHeader instanceof ContentType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$oHeader->setType(Mime::MULTIPART_MIXED);
|
||||
$oHeader->addParameter('boundary', $oBody->getMime()->boundary());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->m_oMessage->setBody($oBody);
|
||||
}
|
||||
|
||||
public function AddPart($sText, $sMimeType = 'text/html')
|
||||
/**
|
||||
* Add a new part to the existing body
|
||||
* @param $sText
|
||||
* @param string $sMimeType
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function AddPart($sText, string $sMimeType = Mime::TYPE_HTML)
|
||||
{
|
||||
if (!array_key_exists('parts', $this->m_aData))
|
||||
{
|
||||
$this->m_aData['parts'] = array();
|
||||
}
|
||||
$this->m_aData['parts'][] = array('text' => $sText, 'mimeType' => $sMimeType);
|
||||
$this->m_oMessage->addPart($sText, $sMimeType);
|
||||
$oNewPart = new Part($sText);
|
||||
$oNewPart->encoding = Mime::ENCODING_8BIT;
|
||||
$oNewPart->type = $sMimeType;
|
||||
$this->m_oMessage->getBody()->addPart($oNewPart);
|
||||
}
|
||||
|
||||
public function AddAttachment($data, $sFileName, $sMimeType)
|
||||
{
|
||||
$oBody = $this->m_oMessage->getBody();
|
||||
|
||||
if(!$oBody->isMultiPart()){
|
||||
$multipart_content = new Part($oBody->generateMessage());
|
||||
$multipart_content->setType($oBody->getParts()[0]->getType());
|
||||
$multipart_content->setBoundary($oBody->getMime()->boundary());
|
||||
|
||||
$oBody = new Laminas\Mime\Message();
|
||||
$oBody->addPart($multipart_content);
|
||||
}
|
||||
|
||||
if (!array_key_exists('attachments', $this->m_aData))
|
||||
{
|
||||
$this->m_aData['attachments'] = array();
|
||||
}
|
||||
$this->m_aData['attachments'][] = array('data' => base64_encode($data), 'filename' => $sFileName, 'mimeType' => $sMimeType);
|
||||
$this->m_oMessage->attach(Swift_Attachment::newInstance($data, $sFileName, $sMimeType));
|
||||
$oNewAttachment = new Part($data);
|
||||
$oNewAttachment->type = $sMimeType;
|
||||
$oNewAttachment->filename = $sFileName;
|
||||
$oNewAttachment->disposition = Mime::DISPOSITION_ATTACHMENT;
|
||||
$oNewAttachment->encoding = Mime::ENCODING_BASE64;
|
||||
|
||||
|
||||
$oBody->addPart($oNewAttachment);
|
||||
|
||||
if($oBody->isMultiPart()){
|
||||
$oContentTypeHeader = $this->m_oMessage->getHeaders();
|
||||
foreach ($oContentTypeHeader as $oHeader) {
|
||||
if (!$oHeader instanceof ContentType) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$oHeader->setType(Mime::MULTIPART_MIXED);
|
||||
$oHeader->addParameter('boundary', $oBody->getMime()->boundary());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->m_oMessage->setBody($oBody);
|
||||
}
|
||||
|
||||
public function SetSubject($sSubject)
|
||||
@@ -409,7 +539,7 @@ class EMail
|
||||
public function GetRecipientTO($bAsString = false)
|
||||
{
|
||||
$aRes = $this->m_oMessage->getTo();
|
||||
if ($aRes === null)
|
||||
if ($aRes === null || $aRes->count() === 0)
|
||||
{
|
||||
// There is no "To" header field
|
||||
$aRes = array();
|
||||
@@ -417,8 +547,10 @@ class EMail
|
||||
if ($bAsString)
|
||||
{
|
||||
$aStrings = array();
|
||||
foreach ($aRes as $sEmail => $sName)
|
||||
foreach ($aRes as $oEmail)
|
||||
{
|
||||
$sName = $oEmail->getName();
|
||||
$sEmail = $oEmail->getEmail();
|
||||
if (is_null($sName))
|
||||
{
|
||||
$aStrings[] = $sEmail;
|
||||
@@ -483,77 +615,4 @@ class EMail
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Extension to SwiftMailer: "debug" transport that pretends messages have been sent,
|
||||
* but just log them to a file.
|
||||
*
|
||||
* @package Swift
|
||||
* @author Denis Flaven
|
||||
*/
|
||||
class Swift_Transport_LogFileTransport extends Swift_Transport_NullTransport
|
||||
{
|
||||
protected $sLogFile;
|
||||
|
||||
/**
|
||||
* Sends the given message.
|
||||
*
|
||||
* @param Swift_Mime_Message $message
|
||||
* @param string[] $failedRecipients An array of failures by-reference
|
||||
*
|
||||
* @return int The number of sent emails
|
||||
*/
|
||||
public function send(Swift_Mime_Message $message, &$failedRecipients = null)
|
||||
{
|
||||
$hFile = @fopen($this->sLogFile, 'a');
|
||||
if ($hFile)
|
||||
{
|
||||
$sTxt = "================== ".date('Y-m-d H:i:s')." ==================\n";
|
||||
$sTxt .= $message->toString()."\n";
|
||||
|
||||
@fwrite($hFile, $sTxt);
|
||||
@fclose($hFile);
|
||||
}
|
||||
|
||||
return parent::send($message, $failedRecipients);
|
||||
}
|
||||
|
||||
public function setLogFile($sFilename)
|
||||
{
|
||||
$this->sLogFile = $sFilename;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pretends messages have been sent, but just log them to a file.
|
||||
*
|
||||
* @package Swift
|
||||
* @author Denis Flaven
|
||||
*/
|
||||
class Swift_LogFileTransport extends Swift_Transport_LogFileTransport
|
||||
{
|
||||
/**
|
||||
* Create a new LogFileTransport.
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
call_user_func_array(
|
||||
array($this, 'Swift_Transport_LogFileTransport::__construct'),
|
||||
Swift_DependencyContainer::getInstance()
|
||||
->createDependenciesFor('transport.null')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new LogFileTransport instance.
|
||||
*
|
||||
* @return Swift_LogFileTransport
|
||||
*/
|
||||
public static function newInstance()
|
||||
{
|
||||
return new self();
|
||||
}
|
||||
}
|
||||
@@ -455,7 +455,6 @@ class LogFileNameBuilderFactory
|
||||
class FileLog
|
||||
{
|
||||
protected $oFileNameBuilder;
|
||||
protected $bHasSQLite;
|
||||
|
||||
/**
|
||||
* FileLog constructor.
|
||||
@@ -468,22 +467,6 @@ class FileLog
|
||||
public function __construct($sFileName = '')
|
||||
{
|
||||
$this->oFileNameBuilder = LogFileNameBuilderFactory::GetInstance($sFileName);
|
||||
$sLogFilePath = $this->oFileNameBuilder->GetLogFilePath();
|
||||
$this->bHasSQLite = class_exists('SQLite3');
|
||||
if ($this->bHasSQLite) {
|
||||
if (empty($sLogFilePath)) {
|
||||
return;
|
||||
}
|
||||
$bCreate = false;
|
||||
$sDBFilePath = "$sLogFilePath.db";
|
||||
if (!is_file($sDBFilePath)) {
|
||||
$bCreate = true;
|
||||
}
|
||||
$this->DB = new SQLite3($sDBFilePath);
|
||||
if ($bCreate) {
|
||||
$this->DB->exec('CREATE TABLE log (id INTEGER PRIMARY KEY AUTOINCREMENT, date TEXT, level TEXT, user TEXT, content LONGTEXT, context LONGTEXT, channel TEXT)');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function Error($sText, $sChannel = '', $aContext = array())
|
||||
@@ -519,17 +502,6 @@ class FileLog
|
||||
|
||||
protected function Write($sText, $sLevel = '', $sChannel = '', $aContext = array())
|
||||
{
|
||||
if ($this->bHasSQLite) {
|
||||
$stmt = $this->DB->prepare('INSERT INTO log (date, level, user, content, context, channel) VALUES (:date, :level, :user, :content, :context, :channel)');
|
||||
$stmt->bindValue(':date', date('Y-m-d H:i:s'));
|
||||
$stmt->bindValue(':level', $sLevel);
|
||||
$stmt->bindValue(':user', LogAPI::GetUserInfo());
|
||||
$stmt->bindValue(':content', $sText);
|
||||
$stmt->bindValue(':context', empty($aContext) ? '' : var_export($aContext, true));
|
||||
$stmt->bindValue(':channel', $sChannel);
|
||||
$stmt->execute();
|
||||
}
|
||||
|
||||
$sTextPrefix = empty($sLevel) ? '' : (str_pad($sLevel, 7));
|
||||
$sTextPrefix .= ' | ';
|
||||
$sTextPrefix .= str_pad(LogAPI::GetUserInfo(), 5)." | ";
|
||||
@@ -572,7 +544,13 @@ class LogChannels
|
||||
{
|
||||
public const APC = 'apc';
|
||||
|
||||
public const CLI = 'CLI';
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.0.1 N°4849
|
||||
*/
|
||||
public const NOTIFICATIONS = 'notifications';
|
||||
|
||||
public const CLI = 'CLI';
|
||||
|
||||
/**
|
||||
* @var string
|
||||
@@ -1032,6 +1010,11 @@ class DeadLockLog extends LogAPI
|
||||
class DeprecatedCallsLog extends LogAPI
|
||||
{
|
||||
public const ENUM_CHANNEL_PHP_METHOD = 'deprecated-php-method';
|
||||
/**
|
||||
* @var string
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public const ENUM_CHANNEL_PHP_ENDPOINT = 'deprecated-php-endpoint';
|
||||
public const ENUM_CHANNEL_PHP_LIBMETHOD = 'deprecated-php-libmethod';
|
||||
public const ENUM_CHANNEL_FILE = 'deprecated-file';
|
||||
public const CHANNEL_DEFAULT = self::ENUM_CHANNEL_PHP_METHOD;
|
||||
@@ -1244,6 +1227,35 @@ class DeprecatedCallsLog extends LogAPI
|
||||
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_METHOD);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string|null $sAdditionalMessage
|
||||
* @since 3.1.0
|
||||
*/
|
||||
public static function NotifyDeprecatedPhpEndpoint(?string $sAdditionalMessage = null): void
|
||||
{
|
||||
try {
|
||||
if (!static::IsLogLevelEnabled(self::LEVEL_WARNING, self::ENUM_CHANNEL_PHP_ENDPOINT)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (ConfigException $e) {
|
||||
return;
|
||||
}
|
||||
|
||||
$aStack = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3);
|
||||
$iStackDeprecatedMethodLevel = 0; // level 0 = current method, level 1 = method containing the `NotifyDeprecatedPhpMethod` call
|
||||
$sDeprecatedUrl = $_SERVER['REQUEST_URI'];
|
||||
$sCallerFile = $aStack[$iStackDeprecatedMethodLevel]['file'];
|
||||
$sCallerLine = $aStack[$iStackDeprecatedMethodLevel]['line'];
|
||||
$sMessage = "Call to endpoint {$sDeprecatedUrl} in {$sCallerFile}#L{$sCallerLine}";
|
||||
|
||||
if (!is_null($sAdditionalMessage)) {
|
||||
$sMessage .= ' : '.$sAdditionalMessage;
|
||||
}
|
||||
|
||||
static::Warning($sMessage, self::ENUM_CHANNEL_PHP_ENDPOINT);
|
||||
}
|
||||
|
||||
public static function Log($sLevel, $sMessage, $sChannel = null, $aContext = array()): void
|
||||
{
|
||||
if (true === utils::IsDevelopmentEnvironment()) {
|
||||
|
||||
@@ -7145,20 +7145,28 @@ abstract class MetaModel
|
||||
/**
|
||||
* @param string $sClass
|
||||
* @param string $sAttCode
|
||||
* @param $value
|
||||
* @param mixed $value
|
||||
* @param bool $bMustBeFoundUnique
|
||||
* @param bool $bAllowAllData
|
||||
*
|
||||
* @return \DBObject if $bMustBeFoundUnique=true and no object or multiple objects found will throw a CoreException
|
||||
* else will return null
|
||||
*
|
||||
* @return \DBObject
|
||||
* @throws \CoreException
|
||||
* @throws \Exception
|
||||
* @throws \CoreUnexpectedValue
|
||||
* @throws \MissingQueryArgument
|
||||
* @throws \MySQLException
|
||||
* @throws \MySQLHasGoneAwayException
|
||||
*
|
||||
* @since 2.7.7 Add new $bAllowAllData parameter
|
||||
*/
|
||||
public static function GetObjectByColumn($sClass, $sAttCode, $value, $bMustBeFoundUnique = true)
|
||||
public static function GetObjectByColumn($sClass, $sAttCode, $value, $bMustBeFoundUnique = true, $bAllowAllData = false)
|
||||
{
|
||||
if (!isset(self::$m_aCacheObjectByColumn[$sClass][$sAttCode][$value]))
|
||||
{
|
||||
if (!isset(self::$m_aCacheObjectByColumn[$sClass][$sAttCode][$value])) {
|
||||
self::_check_subclass($sClass);
|
||||
|
||||
$oObjSearch = new DBObjectSearch($sClass);
|
||||
$oObjSearch->AllowAllData($bAllowAllData);
|
||||
$oObjSearch->AddCondition($sAttCode, $value, '=');
|
||||
$oSet = new DBObjectSet($oObjSearch);
|
||||
if ($oSet->Count() == 1)
|
||||
|
||||
@@ -135,6 +135,7 @@ class ObjectResult
|
||||
*/
|
||||
class RestResultWithObjects extends RestResult
|
||||
{
|
||||
/** @var array "DBObject_class:DBObject_key" as key, {@see \ObjectResult} as value */
|
||||
public $objects;
|
||||
|
||||
/**
|
||||
|
||||
@@ -14,7 +14,7 @@ $ibo-navigation-menu--body--background-color: $ibo-color-blue-grey-900 !default;
|
||||
$ibo-navigation-menu--body--text-color: $ibo-color-grey-300 !default;
|
||||
|
||||
$ibo-navigation-menu--top-part--height: 120px !default;
|
||||
$ibo-navigation-menu--top-part--padding-y: $ibo-navigation-menu--body--padding-y !default;
|
||||
$ibo-navigation-menu--top-part--padding-y: $ibo-spacing-400 !default;
|
||||
$ibo-navigation-menu--top-part--padding-x: $ibo-navigation-menu--body--padding-x !default;
|
||||
$ibo-navigation-menu--top-part--elements-spacing: 20px !default;
|
||||
|
||||
@@ -70,13 +70,13 @@ $ibo-navigation-menu--square-company-logo--width: 38px !default;
|
||||
$ibo-navigation-menu--square-company-logo--height: 38px !default;
|
||||
$ibo-navigation-menu--square-company-logo--margin-top: $ibo-spacing-0 !default;
|
||||
$ibo-navigation-menu--square-company-logo--margin-x: -5px !default;
|
||||
$ibo-navigation-menu--square-company-logo--margin-bottom: $ibo-navigation-menu--body--padding-y * 2 !default;
|
||||
$ibo-navigation-menu--square-company-logo--margin-bottom: ($ibo-navigation-menu--body--padding-y * 2) + 12px !default; /* +12px to keep burger & menu groups icons align in both expanded and collapsed mode */
|
||||
|
||||
$ibo-navigation-menu--full-company-logo--width: $ibo-navigation-menu--body--width-expanded !default;
|
||||
$ibo-navigation-menu--full-company-logo--height: 70px !default;
|
||||
$ibo-navigation-menu--full-company-logo--margin-top: $ibo-spacing-0 !default;
|
||||
$ibo-navigation-menu--full-company-logo--margin-right: $ibo-spacing-0 !default;
|
||||
$ibo-navigation-menu--full-company-logo--margin-bottom: $ibo-spacing-0 !default;
|
||||
$ibo-navigation-menu--full-company-logo--margin-bottom: $ibo-spacing-400 !default;
|
||||
$ibo-navigation-menu--full-company-logo--margin-left: -$ibo-navigation-menu--body--padding-y !default;
|
||||
$ibo-navigation-menu--full-company-logo--image--margin-x: auto !default;
|
||||
$ibo-navigation-menu--full-company-logo--image--margin-y: $ibo-spacing-0 !default;
|
||||
|
||||
20
css/backoffice/pages/_about.scss
Normal file
20
css/backoffice/pages/_about.scss
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
$ibo-about-box--top-part--children--padding-y: $ibo-spacing-500 !default;
|
||||
$ibo-about-box--top-part--children--padding-x: $ibo-spacing-400 !default;
|
||||
$ibo-about-box--top-part--children--margin-y: auto !default;
|
||||
$ibo-about-box--top-part--children--margin-x: auto !default;
|
||||
$ibo-about-box--top-part--children--width: 50% !default;
|
||||
|
||||
.ibo-about-box--top-part{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-content: center;
|
||||
> div{
|
||||
padding: $ibo-about-box--top-part--children--padding-y $ibo-about-box--top-part--children--padding-x;
|
||||
margin: $ibo-about-box--top-part--children--margin-y $ibo-about-box--top-part--children--margin-x;
|
||||
width: $ibo-about-box--top-part--children--width;
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
|
||||
@import "about";
|
||||
@import "base";
|
||||
@import "preferences";
|
||||
@import "attachments";
|
||||
|
||||
2
css/backoffice/vendors/_ckeditor.scss
vendored
2
css/backoffice/vendors/_ckeditor.scss
vendored
@@ -49,7 +49,7 @@ $ibo-vendors-ckeditor--autocomplete-item-title--text-color: #3A3A3A !default;
|
||||
padding: $ibo-vendors-highlightjs--padding !important;
|
||||
box-shadow: 0 0px 3px 2px inset rgba(0, 0, 0, 0.4);
|
||||
border-radius: $ibo-vendors-highlightjs--border-radius;
|
||||
white-space: pre-line;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.ibo-hljs-container{
|
||||
|
||||
@@ -2582,6 +2582,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&[data-attribute-type="AttributeDuration"] {
|
||||
.field_value_container {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.one-col-details .details .field_container.field_small {
|
||||
|
||||
@@ -59,8 +59,8 @@ a:hover {
|
||||
padding-right: 20px;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
height: 54px;
|
||||
margin-top: 150px;
|
||||
height: 94px;
|
||||
margin-top: 110px;
|
||||
}
|
||||
|
||||
#login-content {
|
||||
@@ -75,9 +75,10 @@ a:hover {
|
||||
{
|
||||
#login-logo {
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
#login-content {
|
||||
margin-top: 74px;
|
||||
margin-top: 94px;
|
||||
}
|
||||
h1 {
|
||||
margin-top: 0;
|
||||
@@ -86,7 +87,7 @@ a:hover {
|
||||
|
||||
#login-logo img {
|
||||
border: 0;
|
||||
max-height: 54px;
|
||||
max-height: 94px;
|
||||
}
|
||||
|
||||
#login-form {
|
||||
|
||||
@@ -14,34 +14,4 @@
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
*/
|
||||
body {
|
||||
display: block;
|
||||
}
|
||||
/* Landing page */
|
||||
#uwp-main-container {
|
||||
margin-top: 40px;
|
||||
}
|
||||
#uwp-main-container #uwp-logo, #uwp-main-container #uwp-title {
|
||||
vertical-align: middle;
|
||||
}
|
||||
#uwp-main-container #uwp-title {
|
||||
margin-left: 25px;
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
}
|
||||
#uwp-main-container #uwp-description {
|
||||
margin-bottom: 25px;
|
||||
}
|
||||
#uwp-main-container .uwp-text-hint--icon {
|
||||
font-size: 12px;
|
||||
margin-left: 5px;
|
||||
color: #939191;
|
||||
}
|
||||
#uwp-main-container #uwp-bottom-buttons {
|
||||
margin-top: 25px;
|
||||
text-align: right;
|
||||
}
|
||||
#uwp-main-container #uwp-bottom-buttons .btn ~ .btn {
|
||||
margin-left: 8px;
|
||||
}
|
||||
*/body{display:block}#uwp-main-container{margin-top:40px}#uwp-main-container #uwp-logo,#uwp-main-container #uwp-title{vertical-align:middle;max-height:74px}#uwp-main-container #uwp-title{margin-left:25px;font-size:20px;font-weight:bold}#uwp-main-container #uwp-description{margin-bottom:25px}#uwp-main-container .uwp-text-hint--icon{font-size:12px;margin-left:5px;color:#939191}#uwp-main-container #uwp-bottom-buttons{margin-top:25px;text-align:right}#uwp-main-container #uwp-bottom-buttons .btn~.btn{margin-left:8px}
|
||||
@@ -29,6 +29,7 @@ body{
|
||||
#uwp-logo,
|
||||
#uwp-title{
|
||||
vertical-align: middle;
|
||||
max-height: 74px;
|
||||
}
|
||||
#uwp-title{
|
||||
margin-left: 25px;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<constants>
|
||||
</constants>
|
||||
<classes>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-cas/3.0.1',
|
||||
'authent-cas/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -20,9 +20,9 @@
|
||||
|
||||
* @copyright Copyright (C) 2021 Combodo SARL
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:UserExternal' => 'Externer Benutzer',
|
||||
'Class:UserExternal+' => 'Externe authentifizierter '.ITOP_APPLICATION_SHORT.'-Benutzer',
|
||||
'Class:UserExternal+' => 'Extern authentifizierter '.ITOP_APPLICATION_SHORT.'-Benutzer',
|
||||
));
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-external/3.0.1',
|
||||
'authent-external/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="UserLDAP" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
|
||||
@@ -9,7 +9,7 @@ if (function_exists('ldap_connect'))
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-ldap/3.0.1',
|
||||
'authent-ldap/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
|
||||
<module_parameters>
|
||||
<parameters id="authent-local" _delta="define">
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
* @copyright Copyright (C) 2021 Combodo SARL
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:UserLocal' => ITOP_APPLICATION_SHORT.'-Benutzer',
|
||||
@@ -44,5 +44,5 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Error:UserLocalPasswordValidator:UserPasswordPolicyRegex:ValidationFailed' => 'Das Passwort entspricht nicht dem in den Konfigurationsregeln hinterlegten RegEx-Ausdruck',
|
||||
|
||||
'UserLocal:password:expiration' => 'Die folgenden Felder benötigen eine '.ITOP_APPLICATION_SHORT.' Erweiterung',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Setting password expiration to "One-time password" is not allowed for your own User~~',
|
||||
'Class:UserLocal/Error:OneTimePasswordChangeIsNotAllowed' => 'Das setzen des Passwortablaufs auf "Einmalpasswort" ist für den eigenen Benutzer nicht erlaubt.',
|
||||
));
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'authent-local/3.0.1',
|
||||
'authent-local/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<branding>
|
||||
<themes>
|
||||
<theme id="darkmoon" _delta="define">
|
||||
|
||||
@@ -22,5 +22,5 @@
|
||||
*/
|
||||
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'theme:darkmoon' => 'Dark moon~~',
|
||||
));
|
||||
'theme:darkmoon' => 'Dark moon',
|
||||
));
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-backoffice-darkmoon-theme/3.0.1',
|
||||
'combodo-backoffice-darkmoon-theme/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<menus>
|
||||
<menu id="DBToolsMenu" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>30</rank>
|
||||
|
||||
@@ -359,9 +359,7 @@ function DisplayLostAttachments(iTopWebPage &$oP, ApplicationContext &$oAppConte
|
||||
$sHistoryEntry = Dict::Format('DBTools:LostAttachments:History', $oOrmDocument->GetFileName());
|
||||
CMDBObject::SetTrackInfo(UserRights::GetUserFriendlyName());
|
||||
$oChangeOp = MetaModel::NewObject('CMDBChangeOpPlugin');
|
||||
/** @var \Change $oChange */
|
||||
$oChange = CMDBObject::GetCurrentChange();
|
||||
$oChangeOp->Set('change', $oChange->GetKey());
|
||||
// CMDBChangeOp.change will be automatically filled
|
||||
$oChangeOp->Set('objclass', $sTargetClass);
|
||||
$oChangeOp->Set('objkey', $sTargetId);
|
||||
$oChangeOp->Set('description', $sHistoryEntry);
|
||||
|
||||
@@ -24,7 +24,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'DBTools:Class' => 'Klasse',
|
||||
'DBTools:Title' => 'Datenbankpflege-Tools',
|
||||
'DBTools:ErrorsFound' => 'Fehler gefunden',
|
||||
'DBTools:Indication' => 'Wichtig: Nach dem Fixen der Errors in der Datenbank müssen Sie die Analyse erneut laufen lassen, weil durch die Fixes eventuell weitere Inkonsistenzen enstanden sind',
|
||||
'DBTools:Indication' => 'Wichtig: Nach dem Fixen der Errors in der Datenbank müssen Sie die Analyse erneut laufen lassen, weil durch die Fixes eventuell weitere Inkonsistenzen entstanden sind',
|
||||
'DBTools:Disclaimer' => 'DISCLAIMER: FERTIGEN SIE EIN BACKUP IHRER DATENBANK AN, BEVOR SIE DIE FIXES ANWENDEN!',
|
||||
'DBTools:Error' => 'Fehler',
|
||||
'DBTools:Count' => 'Anzahl',
|
||||
@@ -51,7 +51,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'DBAnalyzer-Integrity-MissingExtKey' => 'Fehlender Externer Key %1$s (Spalte: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-InvalidValue' => 'Ungültiger Wert für %1$s (Spalte: `%2$s.%3$s`)',
|
||||
'DBAnalyzer-Integrity-UsersWithoutProfile' => 'Manche Benutzerkonten haben keinerlei zugewiesenes Profil',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Broken hierarchical key `%1$s`~~',
|
||||
'DBAnalyzer-Integrity-HKInvalid' => 'Kaputter hierarchischer Schlüssel `%1$s`',
|
||||
'DBAnalyzer-Fetch-Count-Error' => 'Fetch-Count-Fehler in `%1$s`, %2$d Einträge geholt (fetched) / %3$d gezählt',
|
||||
'DBAnalyzer-Integrity-FinalClass' => 'Das Feld `%2$s`.`%1$s` muss den gleichen Wert `%3$s`.`%1$s` haben',
|
||||
'DBAnalyzer-Integrity-RootFinalClass' => 'Das Feld `%2$s`.`%1$s` muss eine gültige Klasse enthalten',
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'combodo-db-tools/3.0.1',
|
||||
'combodo-db-tools/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -65,6 +65,9 @@ try
|
||||
switch ($sOperation)
|
||||
{
|
||||
case 'add':
|
||||
$oPage = new JsonPage();
|
||||
$oPage->SetOutputDataOnly(true);
|
||||
|
||||
$aResult = array(
|
||||
'error' => '',
|
||||
'att_id' => 0,
|
||||
@@ -111,7 +114,7 @@ try
|
||||
$aResult['error'] = $e->GetMessage();
|
||||
}
|
||||
}
|
||||
$oPage->add(json_encode($aResult));
|
||||
$oPage->SetData($aResult);
|
||||
break;
|
||||
|
||||
case 'remove':
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="Attachment" _delta="define">
|
||||
<parent>DBObject</parent>
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-attachments/3.0.1',
|
||||
'itop-attachments/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<menus>
|
||||
<menu id="BackupStatus" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>50</rank>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
* @copyright Copyright (C) 2021 Combodo SARL
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
|
||||
@@ -35,15 +35,15 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'bkp-mysqldump-issue' => 'mysqldump konnte nicht ausgeführt werden (retcode=%1$d): Stellen Sie sicher, dass das Programm installiert und im angegebenen Pfad verfügbar ist, oder editieren Sie die Konfigurationsdatei um das MySQL bindir anzupassen.',
|
||||
'bkp-missing-dir' => 'Zielverzeichniss <code>%1$s</code> nicht gefunden',
|
||||
'bkp-free-disk-space' => '<b>%1$s frei</b> in <code>%2$s</code>',
|
||||
'bkp-dir-not-writeable' => '%1$s ist nicht schreibbar',
|
||||
'bkp-dir-not-writeable' => '%1$s ist nicht beschreibbar',
|
||||
'bkp-wrong-format-spec' => 'Die verwendete Definition zur Formatierung von Dateinamen ist nicht korrekt (%1$s). Die Standard-Definition %2$s wird verwendet',
|
||||
'bkp-name-sample' => 'Backup-Dateien werden abhängig von Datum, Zeit und Datenbank-Identifier erstellt. Beispiel: %1$s',
|
||||
'bkp-week-days' => 'Backups werden <b>jeden %1$s um %2$s durchgeführt</b>',
|
||||
'bkp-retention' => 'Mindestens <b>%1$d Backups werden im Zielverzeichniss vorgehalten</b>',
|
||||
'bkp-retention' => 'Mindestens <b>%1$d Backups werden im Zielverzeichnis vorgehalten</b>',
|
||||
'bkp-next-to-delete' => 'Wird gelöscht, wenn das nächste Backup angelegt wird (unter Einstellungen "Menge vorhalten")',
|
||||
'bkp-table-file' => 'Datei',
|
||||
'bkp-table-file+' => 'Nur Dateien mit der Endung .zip werden als Backup-Dateien berücksichtigt.',
|
||||
'bkp-table-size' => 'Grösse',
|
||||
'bkp-table-size' => 'Größe',
|
||||
'bkp-table-size+' => '',
|
||||
'bkp-table-actions' => 'Aktionen',
|
||||
'bkp-table-actions+' => '',
|
||||
@@ -51,7 +51,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'bkp-status-backups-manual' => 'Manuelle Backups',
|
||||
'bkp-status-backups-none' => 'Kein Backup vorhanden',
|
||||
'bkp-next-backup' => 'Das nächste Backup wird am <b>%1$s</b> (%2$s) um %3$s durchgeführt',
|
||||
'bkp-next-backup-unknown' => 'The next backup is <b>not scheduled</b> yet.~~',
|
||||
'bkp-next-backup-unknown' => 'Das nächste Backup ist <b>noch nicht geplant</b>.',
|
||||
'bkp-button-backup-now' => 'Starte Backup',
|
||||
'bkp-button-restore-now' => 'Wiederherstellen!',
|
||||
'bkp-confirm-backup' => 'Bitte bestätigen Sie, dass Sie jetzt ein Backup erstellen wollen.',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-backup/3.0.1',
|
||||
'itop-backup/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<constants></constants>
|
||||
<classes>
|
||||
<class id="lnkFunctionalCIToTicket" _delta="define">
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-cmdb-ticket/3.0.1',
|
||||
'itop-bridge-cmdb-ticket/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="lnkVirtualDeviceToVolume" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-bridge-virtualization-storage/3.0.1',
|
||||
'itop-bridge-virtualization-storage/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="Change" _delta="define">
|
||||
<parent>Ticket</parent>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt-itil/3.0.1',
|
||||
'itop-change-mgmt-itil/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="Change" _delta="define">
|
||||
<parent>Ticket</parent>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
* @copyright Copyright (C) 2021 Combodo SARL
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Menu:ChangeManagement' => 'Change Management',
|
||||
@@ -98,7 +98,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:Change/Attribute:reject_reason+' => '',
|
||||
'Class:Change/Attribute:changemanager_id' => 'Change Manager',
|
||||
'Class:Change/Attribute:changemanager_id+' => '',
|
||||
'Class:Change/Attribute:changemanager_email' => 'Change Manager Email',
|
||||
'Class:Change/Attribute:changemanager_email' => 'Change Manager E-Mail',
|
||||
'Class:Change/Attribute:changemanager_email+' => '',
|
||||
'Class:Change/Attribute:parent_id' => 'Parent Change',
|
||||
'Class:Change/Attribute:parent_id+' => '',
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-change-mgmt/3.0.1',
|
||||
'itop-change-mgmt/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
@@ -85,7 +85,7 @@ class ChangeManagementInstaller extends ModuleInstallerAPI
|
||||
|
||||
if (CMDBSource::IsField($sSourceTable, $sField) && CMDBSource::IsField($sTargetTable, $sField) && CMDBSource::IsField($sSourceTable, $sSourceKeyField) && CMDBSource::IsField($sTargetTable, $sTargetKeyField))
|
||||
{
|
||||
SetupWebPage::log_info("Issue #464 - Copying change/start_date into ticket/start_date");
|
||||
SetupLog::Info("Issue #464 - Copying change/start_date into ticket/start_date");
|
||||
$sRepair = "UPDATE `$sTargetTable`, `$sSourceTable` SET `$sTargetTable`.`$sField` = `$sSourceTable`.`$sField` WHERE `$sTargetTable`.`$sField` IS NULL AND`$sTargetTable`.`$sTargetKeyField` = `$sSourceTable`.`$sSourceKeyField`";
|
||||
CMDBSource::Query($sRepair);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<classes>
|
||||
<class id="FunctionalCI" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
@@ -5828,30 +5828,69 @@
|
||||
<type>Overload-cmdbAbstractObject</type>
|
||||
<code><![CDATA[ protected function UpdateConnectedNetworkDevice()
|
||||
{
|
||||
$oDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'));
|
||||
if (is_object($oDevice) && (get_class($oDevice) == 'NetworkDevice'))
|
||||
{
|
||||
// Note: in case a port has been changed, search with the original values
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport";
|
||||
$aFields = array('networkdevice_id','connectableci_id','network_port','device_port','connection_type');
|
||||
$aChanges = $this->ListPreviousValuesForUpdatedAttributes();
|
||||
$aPrev = array(); // Previous values of the current link object before it was modified
|
||||
foreach ($aFields as $sFieldCode) {
|
||||
$aPrev[$sFieldCode] = array_key_exists($sFieldCode, $aChanges) ? $aChanges[$sFieldCode] : $this->Get($sFieldCode);
|
||||
}
|
||||
$sPrevLink = ($aPrev['connection_type'] == 'uplink') ? 'downlink' : 'uplink';
|
||||
$sConnLink = ($this->Get('connection_type') == 'uplink') ? 'downlink' : 'uplink';
|
||||
|
||||
$oNewDevice = MetaModel::GetObject('ConnectableCI', $this->Get('connectableci_id'), false);
|
||||
$oPrevDevice = MetaModel::GetObject('ConnectableCI', $aPrev['connectableci_id'], false);
|
||||
$bNew = (is_object($oNewDevice) && (get_class($oNewDevice) == 'NetworkDevice'));
|
||||
$bPrev = (is_object($oPrevDevice) && (get_class($oPrevDevice) == 'NetworkDevice'));
|
||||
$sOQL = "SELECT lnkConnectableCIToNetworkDevice WHERE connectableci_id = :device AND networkdevice_id = :network AND network_port = :nwport AND device_port = :devport AND connection_type = :link";
|
||||
|
||||
if ($bPrev) { // There was a twin
|
||||
// Retrieve twin link using previous values of the current link
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'network' => $aPrev['connectableci_id'],
|
||||
'device' => $aPrev['networkdevice_id'],
|
||||
'devport' => $aPrev['network_port'],
|
||||
'nwport' => $aPrev['device_port'],
|
||||
'link' => $sPrevLink,
|
||||
)
|
||||
);
|
||||
if ($bNew) { // and a twin must still exist, so update the existing
|
||||
while ($oConnection = $oConnectionSet->Fetch()) {
|
||||
$oConnection->Set('networkdevice_id', $this->Get('connectableci_id'));
|
||||
$oConnection->Set('connectableci_id', $this->Get('networkdevice_id'));
|
||||
$oConnection->Set('network_port', $this->Get('device_port'));
|
||||
$oConnection->Set('device_port', $this->Get('network_port'));
|
||||
$oConnection->Set('connection_type',$sConnLink);
|
||||
$oConnection->DBUpdate();
|
||||
}
|
||||
}
|
||||
else { // and no twin is needed anymore, so delete the existing
|
||||
while ($oConnection = $oConnectionSet->Fetch()) {
|
||||
$oConnection->DBDelete();
|
||||
}
|
||||
}
|
||||
}
|
||||
elseif ($bNew) { // There was no twin but a twin must exist now
|
||||
// Search for a twin link using current values inverted
|
||||
$oConnectionSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),
|
||||
array(),
|
||||
array(
|
||||
'network' => $this->Get('connectableci_id'),
|
||||
'device' => $this->Get('networkdevice_id'),
|
||||
'devport' => $this->GetOriginal('network_port'),
|
||||
'nwport' => $this->GetOriginal('device_port'),
|
||||
'devport' => $this->Get('device_port'),
|
||||
'nwport' => $this->Get('network_port'),
|
||||
'link' => $sConnLink,
|
||||
)
|
||||
);
|
||||
$sLink = $this->Get('connection_type');
|
||||
$sConnLink = ($sLink == 'uplink') ? 'downlink' : 'uplink';
|
||||
|
||||
// There should be one link - do it in a safe manner anyway
|
||||
while ($oConnection = $oConnectionSet->Fetch())
|
||||
{
|
||||
$oConnection->Set('connection_type', $sConnLink);
|
||||
$oConnection->Set('network_port', $this->Get('device_port'));
|
||||
$oConnection->Set('device_port', $this->Get('network_port'));
|
||||
$oConnection->DBUpdate();
|
||||
if ($oConnectionSet->Count() == 0) {
|
||||
$oNewLink = new lnkConnectableCIToNetworkDevice();
|
||||
$oNewLink->Set('networkdevice_id', $this->Get('connectableci_id'));
|
||||
$oNewLink->Set('connectableci_id', $this->Get('networkdevice_id'));
|
||||
$oNewLink->Set('network_port', $this->Get('device_port'));
|
||||
$oNewLink->Set('device_port', $this->Get('network_port'));
|
||||
$oNewLink->Set('connection_type', $sConnLink);
|
||||
$oNewLink->DBInsert();
|
||||
}
|
||||
}
|
||||
}]]></code>
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
* @copyright Copyright (C) 2021 Combodo SARL
|
||||
* @licence http://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Relation:impacts/Description' => 'Elemente betroffen von',
|
||||
@@ -32,6 +32,8 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Relation:depends on/Description' => 'Elemente, von denen dieses Element abhängt.',
|
||||
'Relation:depends on/DownStream' => 'Hängt ab von ...',
|
||||
'Relation:depends on/UpStream' => 'Wirkt auf ...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
@@ -264,13 +266,13 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:DatacenterDevice/Attribute:nb_u+' => '',
|
||||
'Class:DatacenterDevice/Attribute:managementip' => 'Management-IP',
|
||||
'Class:DatacenterDevice/Attribute:managementip+' => '',
|
||||
'Class:DatacenterDevice/Attribute:powerA_id' => 'PowerA-Quelle',
|
||||
'Class:DatacenterDevice/Attribute:powerA_id' => 'Strom-A-Quelle',
|
||||
'Class:DatacenterDevice/Attribute:powerA_id+' => '',
|
||||
'Class:DatacenterDevice/Attribute:powerA_name' => 'PowerA-Quellenname',
|
||||
'Class:DatacenterDevice/Attribute:powerA_name' => 'Strom-A-Quellenname',
|
||||
'Class:DatacenterDevice/Attribute:powerA_name+' => '',
|
||||
'Class:DatacenterDevice/Attribute:powerB_id' => 'PowerB-Quelle',
|
||||
'Class:DatacenterDevice/Attribute:powerB_id' => 'Strom-B-Quelle',
|
||||
'Class:DatacenterDevice/Attribute:powerB_id+' => '',
|
||||
'Class:DatacenterDevice/Attribute:powerB_name' => 'PowerB-Quellenname',
|
||||
'Class:DatacenterDevice/Attribute:powerB_name' => 'Strom-B-Quellenname',
|
||||
'Class:DatacenterDevice/Attribute:powerB_name+' => '',
|
||||
'Class:DatacenterDevice/Attribute:fiberinterfacelist_list' => 'FC-Ports',
|
||||
'Class:DatacenterDevice/Attribute:fiberinterfacelist_list+' => '',
|
||||
@@ -313,7 +315,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:Server+' => '',
|
||||
'Class:Server/Attribute:osfamily_id' => 'OS Familie',
|
||||
'Class:Server/Attribute:osfamily_id+' => '',
|
||||
'Class:Server/Attribute:osfamily_name' => 'OS-Famillenname',
|
||||
'Class:Server/Attribute:osfamily_name' => 'OS-Familienname',
|
||||
'Class:Server/Attribute:osfamily_name+' => '',
|
||||
'Class:Server/Attribute:osversion_id' => 'OS Version',
|
||||
'Class:Server/Attribute:osversion_id+' => '',
|
||||
@@ -1109,7 +1111,7 @@ Dict::Add('DE DE', 'German', 'Deutsch', array(
|
||||
'Class:Model/Attribute:type/Value:TapeLibrary+' => '',
|
||||
'Class:Model/Attribute:type/Value:Phone' => 'Telefon',
|
||||
'Class:Model/Attribute:type/Value:Phone+' => '',
|
||||
'Class:Model/Attribute:physicaldevices_list' => 'Phyische Geräte',
|
||||
'Class:Model/Attribute:physicaldevices_list' => 'Physische Geräte',
|
||||
'Class:Model/Attribute:physicaldevices_list+' => '',
|
||||
'Class:Model/UniquenessRule:name_brand+' => 'Der Modellname für eine Marke muss eindeutig sein',
|
||||
'Class:Model/UniquenessRule:name_brand' => 'Es existiert bereits ein Modell mit diesem Namen für diese Marke',
|
||||
|
||||
@@ -36,6 +36,8 @@ Dict::Add('ES CR', 'Spanish', 'Español, Castellano', array(
|
||||
'Relation:depends on/Description' => 'Elementos de los cuales depende',
|
||||
'Relation:depends on/DownStream' => 'Depende de...',
|
||||
'Relation:depends on/UpStream' => 'Impactos...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ Dict::Add('HU HU', 'Hungarian', 'Magyar', array(
|
||||
'Relation:depends on/Description' => 'Konfigurációs elemtől függnek',
|
||||
'Relation:depends on/DownStream' => 'Függőségek',
|
||||
'Relation:depends on/UpStream' => 'Hatások',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ Dict::Add('IT IT', 'Italian', 'Italiano', array(
|
||||
'Relation:depends on/Description' => 'Elementi di questo elemento dipende da',
|
||||
'Relation:depends on/DownStream' => 'Dipende da...',
|
||||
'Relation:depends on/UpStream' => 'Impatto...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -29,6 +29,8 @@ Dict::Add('JA JP', 'Japanese', '日本語', array(
|
||||
'Relation:depends on/Description' => 'この要素が依存している要素',
|
||||
'Relation:depends on/DownStream' => '依存...',
|
||||
'Relation:depends on/UpStream' => 'インパクト...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -41,6 +41,8 @@ Dict::Add('NL NL', 'Dutch', 'Nederlands', array(
|
||||
'Relation:depends on/Description' => 'Elementen waarvan dit object afhankelijk van is',
|
||||
'Relation:depends on/DownStream' => 'Is afhankelijk van...',
|
||||
'Relation:depends on/UpStream' => 'Impact op...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -35,6 +35,8 @@ Dict::Add('PT BR', 'Brazilian', 'Brazilian', array(
|
||||
'Relation:depends on/Description' => 'Elementos estes, que dependem deste elemento',
|
||||
'Relation:depends on/DownStream' => 'Depende de...',
|
||||
'Relation:depends on/UpStream' => 'Impactos...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -22,6 +22,8 @@ Dict::Add('RU RU', 'Russian', 'Русский', array(
|
||||
'Relation:depends on/Description' => 'Элементы, от которых зависит',
|
||||
'Relation:depends on/DownStream' => 'Зависит от...',
|
||||
'Relation:depends on/UpStream' => 'Влияет на...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ Dict::Add('SK SK', 'Slovak', 'Slovenčina', array(
|
||||
'Relation:depends on/Description' => 'Prvky, od ktorých závisí tento prvok',
|
||||
'Relation:depends on/DownStream' => 'Depends on...~~',
|
||||
'Relation:depends on/UpStream' => 'Impacts...~~',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -36,6 +36,8 @@ Dict::Add('TR TR', 'Turkish', 'Türkçe', array(
|
||||
'Relation:depends on/Description' => 'Bu kaleme bağımlı olan kalemler',
|
||||
'Relation:depends on/DownStream' => 'Bağımlı olanlar...',
|
||||
'Relation:depends on/UpStream' => 'Etkiledikleri...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -34,6 +34,8 @@ Dict::Add('ZH CN', 'Chinese', '简体中文', array(
|
||||
'Relation:depends on/Description' => '该元素依赖的元素...',
|
||||
'Relation:depends on/DownStream' => '依赖于...',
|
||||
'Relation:depends on/UpStream' => '影响...',
|
||||
'Relation:impacts/LoadData' => 'Load data~~',
|
||||
'Relation:impacts/NoFilteredData' => 'please select objects in Graphical view tag~~',
|
||||
));
|
||||
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config-mgmt/3.0.1',
|
||||
'itop-config-mgmt/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -189,14 +189,16 @@ try {
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', 'save'));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('transaction_id', utils::GetNewTransactionId()));
|
||||
|
||||
// - Cancel button
|
||||
//--- Cancel button
|
||||
$oCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('config-cancel'), 'cancel_button', null, true, 'cancel_button');
|
||||
$oCancelButton->SetOnClickJsCode("return ResetConfig();");
|
||||
$oForm->AddSubBlock($oCancelButton);
|
||||
|
||||
// - Submit button
|
||||
//--- Submit button
|
||||
$oSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('config-apply'), null, Dict::S('config-apply'), true, 'submit_button');
|
||||
$oForm->AddSubBlock($oSubmitButton);
|
||||
|
||||
//--- Config editor
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('prev_config', $sOriginalConfigEscaped, 'prev_config'));
|
||||
$oForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('new_config', $sConfigEscaped));
|
||||
$oForm->AddHtml("<div id =\"new_config\" style=\"position: absolute; top: ".$iEditorTopMargin."em; bottom: 0; left: 5px; right: 5px;\"></div>");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<menus>
|
||||
<menu id="ConfigEditor" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>10</rank>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
SetupWebPage::AddModule(
|
||||
__FILE__, // Path to the current file, all other file names are relative to the directory containing this file
|
||||
'itop-config/3.0.1',
|
||||
'itop-config/3.1.0',
|
||||
array(
|
||||
// Identification
|
||||
//
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.0">
|
||||
<itop_design xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="3.1">
|
||||
<menus>
|
||||
<menu id="iTopUpdate" xsi:type="WebPageMenuNode" _delta="define">
|
||||
<rank>60</rank>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user