mirror of
https://github.com/Combodo/iTop.git
synced 2026-05-19 23:32:17 +02:00
Merge branch 'develop' into feature/faf_event_service
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -30,7 +30,6 @@ if (!defined('APPROOT'))
|
||||
}
|
||||
}
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/ajaxwebpage.class.inc.php');
|
||||
require_once(APPROOT.'core/log.class.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ if (!defined('APPROOT'))
|
||||
}
|
||||
}
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/ajaxwebpage.class.inc.php');
|
||||
require_once(APPROOT.'core/log.class.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
|
||||
|
||||
@@ -30,7 +30,6 @@ if (!defined('APPROOT'))
|
||||
}
|
||||
}
|
||||
require_once(APPROOT.'application/application.inc.php');
|
||||
require_once(APPROOT.'application/ajaxwebpage.class.inc.php');
|
||||
require_once(APPROOT.'core/log.class.inc.php');
|
||||
require_once(APPROOT.'application/startup.inc.php');
|
||||
require_once(dirname(__FILE__).'/dbrestore.class.inc.php');
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>");
|
||||
|
||||
@@ -54,6 +54,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
|
||||
'iTopUpdate:UI:Status' => 'Status',
|
||||
'iTopUpdate:UI:Action' => 'Update',
|
||||
'iTopUpdate:UI:Setup' => ITOP_APPLICATION_SHORT.' Setup',
|
||||
'iTopUpdate:UI:History' => 'Versions History',
|
||||
'iTopUpdate:UI:Progress' => 'Progress of the upgrade',
|
||||
|
||||
@@ -81,6 +82,9 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
|
||||
|
||||
|
||||
'iTopUpdate:UI:SetupLaunch' => 'Launch '.ITOP_APPLICATION_SHORT.' Setup',
|
||||
'iTopUpdate:UI:SetupLaunchConfirm' => 'This will launch '.ITOP_APPLICATION_SHORT.' setup, are you sure?',
|
||||
|
||||
// Setup Messages
|
||||
'iTopUpdate:UI:SetupMessage:Ready' => 'Ready to start',
|
||||
'iTopUpdate:UI:SetupMessage:EnterMaintenance' => 'Entering maintenance mode',
|
||||
|
||||
@@ -17,6 +17,7 @@ use Dict;
|
||||
use Exception;
|
||||
use IssueLog;
|
||||
use MetaModel;
|
||||
use SecurityException;
|
||||
use SetupUtils;
|
||||
use utils;
|
||||
|
||||
@@ -211,8 +212,7 @@ class AjaxController extends Controller
|
||||
CoreUpdater::UpdateDatabase();
|
||||
$iResponseCode = 200;
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
catch (Exception $e) {
|
||||
IssueLog::Error("Compile: ".$e->getMessage());
|
||||
$aParams['sError'] = $e->getMessage();
|
||||
$iResponseCode = 500;
|
||||
@@ -220,4 +220,22 @@ class AjaxController extends Controller
|
||||
|
||||
$this->DisplayJSONPage($aParams, $iResponseCode);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws \SecurityException if CSRF token invalid
|
||||
*
|
||||
* @since 3.1.0 N°4919
|
||||
*/
|
||||
public function OperationLaunchSetup()
|
||||
{
|
||||
$sTransactionId = utils::ReadParam('transaction_id', '', false, 'transaction_id');
|
||||
if (false === utils::IsTransactionValid($sTransactionId)) {
|
||||
throw new SecurityException('Access forbidden');
|
||||
}
|
||||
|
||||
$sConfigFile = APPCONF.'production/config-itop.php';
|
||||
@chmod($sConfigFile, 0770); // Allow overwriting the file
|
||||
|
||||
header('Location: ../setup/');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,25 @@ class UpdateController extends Controller
|
||||
$oSet = new DBObjectSet($oFilter, ['installed' => false]); // Most recent first
|
||||
$aParams['oSet'] = $oSet;
|
||||
|
||||
$oConfig = utils::GetConfig();
|
||||
$bConfigParamSetupLaunchButtonEnabled = $oConfig->Get('setup.launch_button.enabled');
|
||||
if (is_null($bConfigParamSetupLaunchButtonEnabled)) {
|
||||
$bIsSetupLaunchButtonEnabled = utils::IsDevelopmentEnvironment();
|
||||
} else if (false === $bConfigParamSetupLaunchButtonEnabled) {
|
||||
$bIsSetupLaunchButtonEnabled = false;
|
||||
} else {
|
||||
$bIsSetupLaunchButtonEnabled = $bConfigParamSetupLaunchButtonEnabled || utils::IsDevelopmentEnvironment();
|
||||
}
|
||||
$aParams['bIsSetupLaunchButtonEnabled'] = $bIsSetupLaunchButtonEnabled;
|
||||
if ($bIsSetupLaunchButtonEnabled) {
|
||||
$sLaunchSetupUrl = utils::GetAbsoluteUrlModulePage('itop-core-update', 'ajax.php',
|
||||
[
|
||||
'operation' => 'LaunchSetup',
|
||||
'transaction_id' => $sTransactionId,
|
||||
]);;
|
||||
$aParams['sLaunchSetupUrl'] = $sLaunchSetupUrl;
|
||||
}
|
||||
|
||||
$this->DisplayPage($aParams);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,6 +87,14 @@
|
||||
|
||||
{% EndUIFieldSet %}
|
||||
|
||||
{% if bIsSetupLaunchButtonEnabled %}
|
||||
{% UIFieldSet Standard {'sLegend':'iTopUpdate:UI:Setup'|dict_s} %}
|
||||
{% UIForm Standard {'sId':'launch-setup-form', Action:sLaunchSetupUrl} %}
|
||||
{% UIButton ForDestructiveAction {'sLabel':'iTopUpdate:UI:SetupLaunch'|dict_s, 'sName':'launch-setup', 'sValue':'launch-setup', 'bIsSubmit':true, 'sId':'launch-setup'} %}
|
||||
{% EndUIForm %}
|
||||
{% EndUIFieldSet %}
|
||||
{% endif %}
|
||||
|
||||
{% UIFieldSet Standard {'sLegend':'iTopUpdate:UI:History'|dict_s} %}
|
||||
{% UIDataTable ForRendering {'sListId':'iboupdatehistory', 'oSet':oSet} %}{% EndUIDataTable %}
|
||||
{% EndUIFieldSet %}
|
||||
|
||||
@@ -101,3 +101,7 @@ $("#check-update").on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
|
||||
$("#launch-setup-form").on("submit", function () {
|
||||
return window.confirm("{{ 'iTopUpdate:UI:SetupLaunchConfirm'|dict_s }}");
|
||||
});
|
||||
@@ -22,18 +22,20 @@
|
||||
* @copyright Copyright (C) 2010-2021 Combodo SARL
|
||||
* @license http://opensource.org/licenses/AGPL-3.0
|
||||
*/
|
||||
if (!defined('__DIR__')) define('__DIR__', dirname(__FILE__));
|
||||
require_once (APPROOT.'application/webpage.class.inc.php');
|
||||
require_once (APPROOT.'application/utils.inc.php');
|
||||
require_once (APPROOT.'core/log.class.inc.php');
|
||||
if (!defined('__DIR__')) {
|
||||
define('__DIR__', dirname(__FILE__));
|
||||
}
|
||||
|
||||
require_once(APPROOT.'application/utils.inc.php');
|
||||
require_once(APPROOT.'core/log.class.inc.php');
|
||||
IssueLog::Enable(APPROOT.'log/error.log');
|
||||
|
||||
require_once (APPROOT.'setup/runtimeenv.class.inc.php');
|
||||
require_once (APPROOT.'setup/backup.class.inc.php');
|
||||
require_once (APPROOT.'core/mutex.class.inc.php');
|
||||
require_once (APPROOT.'core/dict.class.inc.php');
|
||||
require_once (APPROOT.'setup/xmldataloader.class.inc.php');
|
||||
require_once (__DIR__.'/hubruntimeenvironment.class.inc.php');
|
||||
require_once(APPROOT.'setup/runtimeenv.class.inc.php');
|
||||
require_once(APPROOT.'setup/backup.class.inc.php');
|
||||
require_once(APPROOT.'core/mutex.class.inc.php');
|
||||
require_once(APPROOT.'core/dict.class.inc.php');
|
||||
require_once(APPROOT.'setup/xmldataloader.class.inc.php');
|
||||
require_once(__DIR__.'/hubruntimeenvironment.class.inc.php');
|
||||
|
||||
/**
|
||||
* Overload of DBBackup to handle logging
|
||||
|
||||
@@ -280,7 +280,6 @@ try {
|
||||
switch ($sTargetRoute) {
|
||||
case 'inform_after_setup':
|
||||
// Hidden IFRAME at the end of the setup
|
||||
require_once(APPROOT.'/application/ajaxwebpage.class.inc.php');
|
||||
$oPage = new NiceWebPage('');
|
||||
$aDataToPost = MakeDataToPost($sTargetRoute);
|
||||
$oPage->add('<form id="hub_launch_form" action="'.$sHubUrlStateless.'" method="post">');
|
||||
|
||||
@@ -1142,39 +1142,40 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// single person
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a departement!
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$iPriority = 1;
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')]))
|
||||
{
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
<code><![CDATA[public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// single person
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a departement!
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'priority');
|
||||
$iPriority = $oAttDef->IsNullAllowed() ? null : $oAttDef->GetDefaultValue();
|
||||
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')])) {
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ComputeValues">
|
||||
<static>false</static>
|
||||
|
||||
@@ -162,12 +162,20 @@ class BrickCollection
|
||||
// - Home
|
||||
$this->aHomeOrdering = $this->aAllowedBricks;
|
||||
usort($this->aHomeOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankHome() > $b->GetRankHome();
|
||||
if ($a->GetRankHome() === $b->GetRankHome()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a->GetRankHome() > $b->GetRankHome() ? 1 : -1;
|
||||
});
|
||||
// - Navigation menu
|
||||
$this->aNavigationMenuOrdering = $this->aAllowedBricks;
|
||||
usort($this->aNavigationMenuOrdering, function (PortalBrick $a, PortalBrick $b) {
|
||||
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu();
|
||||
if ($a->GetRankNavigationMenu() === $b->GetRankNavigationMenu()) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a->GetRankNavigationMenu() > $b->GetRankNavigationMenu() ? 1 : -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -485,7 +485,11 @@ class ManageBrick extends PortalBrick
|
||||
if (!$this->IsGroupingByDistinctValues($sName))
|
||||
{
|
||||
usort($this->aGrouping[$sName]['groups'], function ($a, $b) {
|
||||
return $a['rank'] > $b['rank'];
|
||||
if ($a['rank'] === $b['rank']) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return $a['rank'] > $b['rank'] ? 1 : -1;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -1246,7 +1246,7 @@ class ObjectController extends BrickController
|
||||
}
|
||||
|
||||
$aData['att_id'] = $iAttId;
|
||||
$aData['preview'] = $oDocument->IsPreviewAvailable() ;
|
||||
$aData['preview'] = $oDocument->IsPreviewAvailable();
|
||||
$aData['file_size'] = $oDocument->GetFormattedSize();
|
||||
$aData['creation_date'] = $oAttachment->Get('creation_date');
|
||||
$aData['user_id_friendlyname'] = $oAttachment->Get('user_id_friendlyname');
|
||||
|
||||
@@ -91,7 +91,10 @@ class Lists extends AbstractConfiguration
|
||||
}
|
||||
// - Sorting list items by rank
|
||||
usort($aListItems, function ($a, $b) {
|
||||
return $a['rank'] > $b['rank'];
|
||||
if ($a['rank'] == $b['rank']) {
|
||||
return 0;
|
||||
}
|
||||
return $a['rank'] > $b['rank'] ? 1 : -1;
|
||||
});
|
||||
$aClassLists[$sListId] = $aListItems;
|
||||
}
|
||||
|
||||
@@ -120,17 +120,6 @@ class ObjectFormManager extends FormManager
|
||||
{
|
||||
$aJson = static::DecodeFormManagerData($sJson);
|
||||
|
||||
$oConfig = utils::GetConfig();
|
||||
$bIsContentCheckEnabled = $oConfig->GetModuleSetting(PORTAL_ID, 'enable_formmanager_content_check', true);
|
||||
if ($bIsContentCheckEnabled && (false === $bTrustContent)) {
|
||||
/** @noinspection NestedPositiveIfStatementsInspection */
|
||||
if (isset($aJson['formproperties']['layout']['type']) && ($aJson['formproperties']['layout']['type'] === 'twig')) {
|
||||
// There will be an IssueLog above in the hierarchy due to the exception, but we are logging here so that we can output the JSON data !
|
||||
IssueLog::Error('Portal received a query with forbidden twig content!', \LogChannels::PORTAL, ['formmanager_data' => $aJson]);
|
||||
throw new \SecurityException('Twig content not allowed in this context!');
|
||||
}
|
||||
}
|
||||
|
||||
/** @var \Combodo\iTop\Portal\Form\ObjectFormManager $oFormManager */
|
||||
$oFormManager = parent::FromJSON($sJson);
|
||||
|
||||
@@ -703,7 +692,7 @@ class ObjectFormManager extends FormManager
|
||||
|
||||
/** @var Field $oField */
|
||||
$oField = null;
|
||||
if (is_callable(get_class($oAttDef).'::MakeFormField'))
|
||||
if (is_callable([$oAttDef, 'MakeFormField']))
|
||||
{
|
||||
$oField = $oAttDef->MakeFormField($this->oObject);
|
||||
}
|
||||
@@ -1185,16 +1174,18 @@ class ObjectFormManager extends FormManager
|
||||
$sObjectClass = get_class($this->oObject);
|
||||
|
||||
try {
|
||||
// modification flags
|
||||
$bIsNew = $this->oObject->IsNew();
|
||||
$bWasModified = $this->oObject->IsModified();
|
||||
$bActivateTriggers = (!$bIsNew && $bWasModified);
|
||||
|
||||
// Forcing allowed writing on the object if necessary. This is used in some particular cases.
|
||||
$bAllowWrite = ($sObjectClass === 'Person' && $this->oObject->GetKey() == UserRights::GetContactId());
|
||||
$bAllowWrite = $this->oContainer->get('security_helper')->IsActionAllowed($bIsNew ? UR_ACTION_CREATE : UR_ACTION_MODIFY, $sObjectClass, $this->oObject->GetKey());
|
||||
if ($bAllowWrite) {
|
||||
$this->oObject->AllowWrite(true);
|
||||
}
|
||||
|
||||
// Writing object to DB
|
||||
$bIsNew = $this->oObject->IsNew();
|
||||
$bWasModified = $this->oObject->IsModified();
|
||||
$bActivateTriggers = (!$bIsNew && $bWasModified);
|
||||
try
|
||||
{
|
||||
$this->oObject->DBWrite();
|
||||
|
||||
@@ -103,6 +103,12 @@ class SecurityHelper
|
||||
return false;
|
||||
}
|
||||
|
||||
// Forcing allowed writing on the object if necessary. This is used in some particular cases.
|
||||
$bObjectIsCurrentUser = ($sObjectClass === 'Person' && $sObjectId == UserRights::GetContactId());
|
||||
if(in_array($sAction , array(UR_ACTION_MODIFY, UR_ACTION_READ)) && $bObjectIsCurrentUser){
|
||||
return true;
|
||||
}
|
||||
|
||||
// Checking the scopes layer
|
||||
// - Transforming scope action as there is only 2 values
|
||||
$sScopeAction = ($sAction === UR_ACTION_READ) ? UR_ACTION_READ : UR_ACTION_MODIFY;
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
namespace Combodo\iTop\Portal\Twig;
|
||||
|
||||
use AttributeDate;
|
||||
use Combodo\iTop\Application\TwigBase\Twig\Extension;
|
||||
use Twig\Extension\AbstractExtension;
|
||||
|
||||
use AttributeDateTime;
|
||||
@@ -33,194 +34,29 @@ use MetaModel;
|
||||
/**
|
||||
* Class AppExtension
|
||||
*
|
||||
* Automatically loaded by portal's Symfony configuration to register TWIG extensions.
|
||||
* The class must be kept by it is using the factorized filters/functions of the iTop core.
|
||||
*
|
||||
* @package Combodo\iTop\Portal\Twig
|
||||
* @since 2.7.0
|
||||
* @author Bruno Da Silva <bruno.dasilva@combodo.com>
|
||||
* @deprected 3.1.0 N°4287
|
||||
*/
|
||||
class AppExtension extends AbstractExtension
|
||||
{
|
||||
/**
|
||||
* @return array|\Twig\TwigFilter[]|\Twig_SimpleFilter[]
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getFilters()
|
||||
{
|
||||
$filters = array();
|
||||
// Filter to translate a string via the Dict::S function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_s }}
|
||||
$filters[] = new Twig_SimpleFilter('dict_s',
|
||||
function ($sStringCode, $sDefault = null, $bUserLanguageOnly = false) {
|
||||
return Dict::S($sStringCode, $sDefault, $bUserLanguageOnly);
|
||||
}
|
||||
);
|
||||
|
||||
// Filter to format a string via the Dict::Format function
|
||||
// Usage in twig: {{ 'String:ToTranslate'|dict_format() }}
|
||||
$filters[] = new Twig_SimpleFilter('dict_format',
|
||||
function ($sStringCode, $sParam01 = null, $sParam02 = null, $sParam03 = null, $sParam04 = null) {
|
||||
return Dict::Format($sStringCode, $sParam01, $sParam02, $sParam03, $sParam04);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter to format output
|
||||
* example a DateTime is converted to user format
|
||||
* Usage in twig: {{ 'String:ToFormat'|output_format }}
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$filters[] = new Twig_SimpleFilter('date_format',
|
||||
function ($sDate) {
|
||||
try
|
||||
{
|
||||
if (preg_match('@^\d\d\d\d-\d\d-\d\d \d\d:\d\d:\d\d$@', trim($sDate)))
|
||||
{
|
||||
return AttributeDateTime::GetFormat()->Format($sDate);
|
||||
}
|
||||
if (preg_match('@^\d\d\d\d-\d\d-\d\d$@', trim($sDate)))
|
||||
{
|
||||
return AttributeDate::GetFormat()->Format($sDate);
|
||||
}
|
||||
}
|
||||
catch (Exception $e)
|
||||
{
|
||||
}
|
||||
|
||||
return $sDate;
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter to format output
|
||||
* example a DateTime is converted to user format
|
||||
* Usage in twig: {{ 'String:ToFormat'|output_format }}
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$filters[] = new Twig_SimpleFilter('size_format',
|
||||
function ($sSize) {
|
||||
return utils::BytesToFriendlyFormat($sSize);
|
||||
}
|
||||
);
|
||||
|
||||
// Filter to enable base64 encode/decode
|
||||
// Usage in twig: {{ 'String to encode'|base64_encode }}
|
||||
$filters[] = new Twig_SimpleFilter('base64_encode', 'base64_encode');
|
||||
$filters[] = new Twig_SimpleFilter('base64_decode', 'base64_decode');
|
||||
|
||||
// Filter to enable json decode (encode already exists)
|
||||
// Usage in twig: {{ aSomeArray|json_decode }}
|
||||
$filters[] = new Twig_SimpleFilter('json_decode', function ($sJsonString, $bAssoc = false) {
|
||||
return json_decode($sJsonString, $bAssoc);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter to sanitize a text
|
||||
* Usage in twig: {{ 'variable_name:to-sanitize'|sanitize(constant('utils::ENUM_SANITIZATION_FILTER_VARIABLE_NAME')) }}
|
||||
*
|
||||
* @uses \utils::Sanitize()
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$filters[] = new Twig_SimpleFilter('sanitize', function (string $sString, string $sFilter) {
|
||||
return utils::Sanitize($sString, '', $sFilter);
|
||||
}
|
||||
);
|
||||
|
||||
/**
|
||||
* Filter to transform the wiki syntax ONLY into HTML.
|
||||
*
|
||||
* @uses \AttributeText::RenderWikiHtml()
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$filters[] = new Twig_SimpleFilter('render_wiki_to_html', function ($sString) {
|
||||
return AttributeText::RenderWikiHtml($sString, true /* Important, otherwise hyperlinks will be tranformed as well */);
|
||||
}
|
||||
);
|
||||
|
||||
// Filter to add itopversion to an url
|
||||
$filters[] = new Twig_SimpleFilter('add_itop_version', function ($sUrl) {
|
||||
$sUrl = utils::AddParameterToUrl($sUrl, 'itopversion', ITOP_VERSION);
|
||||
|
||||
return $sUrl;
|
||||
});
|
||||
|
||||
// Filter to add a module's version to an url
|
||||
$filters[] = new Twig_SimpleFilter('add_module_version', function ($sUrl, $sModuleName) {
|
||||
$sModuleVersion = utils::GetCompiledModuleVersion($sModuleName);
|
||||
$sUrl = utils::AddParameterToUrl($sUrl, 'moduleversion', $sModuleVersion);
|
||||
|
||||
return $sUrl;
|
||||
});
|
||||
|
||||
/**
|
||||
* var_export can be used for example to transform a PHP boolean to 'true' or 'false' strings
|
||||
* @see https://www.php.net/manual/fr/function.var-export.php
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$filters[] = new Twig_SimpleFilter('var_export', 'var_export');
|
||||
|
||||
|
||||
return $filters;
|
||||
return Extension::GetFilters();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array|\Twig\TwigFunction[]|\Twig_SimpleFunction[]
|
||||
* @inheritDoc
|
||||
*/
|
||||
public function getFunctions()
|
||||
{
|
||||
$functions = array();
|
||||
|
||||
// Function to check our current environment
|
||||
// Usage in twig: {% if is_development_environment() %}
|
||||
$functions[] = new Twig_SimpleFunction('is_development_environment', function () {
|
||||
return utils::IsDevelopmentEnvironment();
|
||||
});
|
||||
|
||||
// Function to get configuration parameter
|
||||
// Usage in twig: {{ get_config_parameter('foo') }}
|
||||
$functions[] = new Twig_SimpleFunction('get_config_parameter', function ($sParamName) {
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
|
||||
return $oConfig->Get($sParamName);
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to get a module setting
|
||||
* Usage in twig: {{ get_module_setting(<MODULE_CODE>, <PROPERTY_CODE> [, <DEFAULT_VALUE>]) }}
|
||||
*
|
||||
* @uses Config::GetModuleSetting()
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$functions[] = new Twig_SimpleFunction('get_module_setting',
|
||||
function (string $sModuleCode, string $sPropertyCode, $defaultValue = null) {
|
||||
$oConfig = MetaModel::GetConfig();
|
||||
|
||||
return $oConfig->GetModuleSetting($sModuleCode, $sPropertyCode, $defaultValue);
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to get iTop's app root absolute URL (eg. https://aaa.bbb.ccc/xxx/yyy/)
|
||||
* Usage in twig: {{ get_absolute_url_app_root() }}
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$functions[] = new Twig_SimpleFunction('get_absolute_url_app_root', function () {
|
||||
return utils::GetAbsoluteUrlAppRoot();
|
||||
});
|
||||
|
||||
/**
|
||||
* Function to get iTop's modules root absolute URL (eg. https://aaa.bbb.ccc/xxx/yyy/env-zzz/)
|
||||
* Usage in twig: {{ get_absolute_url_modules_root() }}
|
||||
*
|
||||
* @since 3.0.0
|
||||
*/
|
||||
$functions[] = new Twig_SimpleFunction('get_absolute_url_modules_root', function () {
|
||||
return utils::GetAbsoluteUrlModulesRoot();
|
||||
});
|
||||
|
||||
return $functions;
|
||||
return Extension::GetFunctions();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -172,9 +172,13 @@
|
||||
</value>
|
||||
</values>
|
||||
<sql>priority</sql>
|
||||
<default_value>1</default_value>
|
||||
<default_value>4</default_value>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<display_style>list</display_style>
|
||||
<dependencies>
|
||||
<attribute id="impact"/>
|
||||
<attribute id="urgency"/>
|
||||
</dependencies>
|
||||
</field>
|
||||
<field id="related_change_id" xsi:type="AttributeExternalKey">
|
||||
<filter><![CDATA[SELECT Change WHERE status != "closed"]]></filter>
|
||||
@@ -481,39 +485,40 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// single person
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a departement!
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$iPriority = 1;
|
||||
if (isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')]))
|
||||
{
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
<code><![CDATA[public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// single person
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a departement!
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'priority');
|
||||
$iPriority = $oAttDef->IsNullAllowed() ? null : $oAttDef->GetDefaultValue();
|
||||
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')])) {
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ComputeValues">
|
||||
<static>false</static>
|
||||
@@ -564,10 +569,10 @@
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="related_incident_list">
|
||||
<rank>50</rank>
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
<item id="col:col1">
|
||||
<rank>60</rank>
|
||||
<rank>70</rank>
|
||||
<items>
|
||||
<item id="fieldset:Ticket:baseinfo">
|
||||
<rank>10</rank>
|
||||
@@ -575,31 +580,44 @@
|
||||
<item id="ref">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="title">
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<item id="caller_id">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="status">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="priority">
|
||||
<item id="product">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="service_id">
|
||||
<item id="title">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
<item id="servicesubcategory_id">
|
||||
<item id="description">
|
||||
<rank>70</rank>
|
||||
</item>
|
||||
<item id="product">
|
||||
<rank>80</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="fieldset:Ticket:moreinfo">
|
||||
<rank>20</rank>
|
||||
<items>
|
||||
<item id="service_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="servicesubcategory_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="col:col2">
|
||||
<rank>80</rank>
|
||||
<items>
|
||||
<item id="fieldset:Ticket:Type">
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="impact">
|
||||
<rank>10</rank>
|
||||
@@ -607,18 +625,13 @@
|
||||
<item id="urgency">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<item id="priority">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="col:col2">
|
||||
<rank>70</rank>
|
||||
<items>
|
||||
<item id="fieldset:Ticket:date">
|
||||
<rank>10</rank>
|
||||
<rank>20</rank>
|
||||
<items>
|
||||
<item id="start_date">
|
||||
<rank>10</rank>
|
||||
@@ -637,22 +650,25 @@
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="col:col3">
|
||||
<rank>90</rank>
|
||||
<items>
|
||||
<item id="fieldset:Ticket:contact">
|
||||
<rank>20</rank>
|
||||
<rank>10</rank>
|
||||
<items>
|
||||
<item id="caller_id">
|
||||
|
||||
<item id="team_id">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="team_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="agent_id">
|
||||
<rank>30</rank>
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</item>
|
||||
<item id="fieldset:Ticket:relation">
|
||||
<rank>30</rank>
|
||||
<rank>20</rank>
|
||||
<items>
|
||||
<item id="related_change_id">
|
||||
<rank>10</rank>
|
||||
@@ -743,9 +759,9 @@
|
||||
<menus>
|
||||
<menu id="ProblemManagement" xsi:type="MenuGroup" _delta="define_if_not_exists">
|
||||
<rank>42</rank>
|
||||
<style>
|
||||
<decoration_classes>fas fa-question</decoration_classes>
|
||||
</style>
|
||||
<style>
|
||||
<decoration_classes>fas fa-question</decoration_classes>
|
||||
</style>
|
||||
</menu>
|
||||
<menu id="Problem:Shortcuts" xsi:type="TemplateMenuNode" _delta="define_if_not_exists">
|
||||
<rank>5</rank>
|
||||
|
||||
@@ -1302,39 +1302,40 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// a department
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a person
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$iPriority = 1;
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')]))
|
||||
{
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
<code><![CDATA[public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// a department
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a person
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'priority');
|
||||
$iPriority = $oAttDef->IsNullAllowed() ? null : $oAttDef->GetDefaultValue();
|
||||
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')])) {
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ComputeValues">
|
||||
<static>false</static>
|
||||
|
||||
@@ -1348,39 +1348,40 @@
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<type>LifecycleAction</type>
|
||||
<code><![CDATA[ public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// a department
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a person
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$iPriority = 1;
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')]))
|
||||
{
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
<code><![CDATA[public function ComputePriority()
|
||||
{
|
||||
// priority[impact][urgency]
|
||||
$aPriorities = array(
|
||||
// a department
|
||||
1 => array(
|
||||
1 => 1,
|
||||
2 => 1,
|
||||
3 => 2,
|
||||
4 => 4,
|
||||
),
|
||||
// a group
|
||||
2 => array(
|
||||
1 => 1,
|
||||
2 => 2,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
// a person
|
||||
3 => array(
|
||||
1 => 2,
|
||||
2 => 3,
|
||||
3 => 3,
|
||||
4 => 4,
|
||||
),
|
||||
);
|
||||
$oAttDef = MetaModel::GetAttributeDef(get_class($this), 'priority');
|
||||
$iPriority = $oAttDef->IsNullAllowed() ? null : $oAttDef->GetDefaultValue();
|
||||
|
||||
if (isset($aPriorities[(int)$this->Get('impact')]) && isset($aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')])) {
|
||||
$iPriority = $aPriorities[(int)$this->Get('impact')][(int)$this->Get('urgency')];
|
||||
}
|
||||
return $iPriority;
|
||||
}]]></code>
|
||||
</method>
|
||||
<method id="ComputeValues">
|
||||
<static>false</static>
|
||||
|
||||
@@ -1544,120 +1544,100 @@ public function PrefillSearchForm(&$aContextParam)
|
||||
</reconciliation>
|
||||
</properties>
|
||||
<fields>
|
||||
<field id="name" xsi:type="AttributeString">
|
||||
<sql>name</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="description" xsi:type="AttributeText">
|
||||
<sql>description</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="org_id" xsi:type="AttributeExternalKey">
|
||||
<sql>org_id</sql>
|
||||
<target_class>Organization</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
</field>
|
||||
<field id="organization_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>org_id</extkey_attcode>
|
||||
<target_attcode>name</target_attcode>
|
||||
</field>
|
||||
<field id="slts_list" xsi:type="AttributeLinkedSetIndirect">
|
||||
<linked_class>lnkSLAToSLT</linked_class>
|
||||
<ext_key_to_me>sla_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<ext_key_to_remote>slt_id</ext_key_to_remote>
|
||||
<duplicates/>
|
||||
</field>
|
||||
<field id="customercontracts_list" xsi:type="AttributeLinkedSetIndirect">
|
||||
<linked_class>lnkCustomerContractToService</linked_class>
|
||||
<ext_key_to_me>sla_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<ext_key_to_remote>customercontract_id</ext_key_to_remote>
|
||||
<duplicates>true</duplicates>
|
||||
</field>
|
||||
</fields>
|
||||
<methods>
|
||||
<method id="DoCheckToWrite">
|
||||
<static>false</static>
|
||||
<access>public</access>
|
||||
<code><![CDATA[
|
||||
public function DoCheckToWrite()
|
||||
{
|
||||
parent::DoCheckToWrite();
|
||||
|
||||
$aCustomerContracts = $this->Get("customercontracts_list");
|
||||
foreach ($aCustomerContracts as $sAttCode => $oCustomerContracts)
|
||||
{
|
||||
// Recurse inside the subdirectories
|
||||
$sOql = "SELECT lnkCustomerContractToService AS ccs WHERE ccs.customercontract_id=:customercontract_id AND ccs.service_id=:service_id";
|
||||
$aQueryParams['customercontract_id'] = $oCustomerContracts->Get("customercontract_id");
|
||||
$aQueryParams['service_id'] = $oCustomerContracts->Get("service_id");
|
||||
if ($this->Get("id") != null)
|
||||
{
|
||||
$sOql = $sOql." AND ccs.sla_id!=:sla_id";
|
||||
$aQueryParams['sla_id'] = $this->Get("id");
|
||||
}
|
||||
$oQuery = DBSearch::FromOQL($sOql, $aQueryParams);
|
||||
$oResultSql = new DBObjectSet($oQuery);
|
||||
$oResultSql->OptimizeColumnLoad(['ccs' => ['customercontract_name','service_name']]);
|
||||
if ($aCurrentRow = $oResultSql->Fetch())
|
||||
{
|
||||
$this->m_aCheckIssues[] = Dict::Format('Class:SLA/Error:UniqueLnkCustomerContractToService',$aCurrentRow->Get('customercontract_name'),$aCurrentRow->Get('service_name'));
|
||||
}
|
||||
}
|
||||
}
|
||||
]]></code>
|
||||
</method>
|
||||
</methods>
|
||||
<field id="name" xsi:type="AttributeString">
|
||||
<sql>name</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
</field>
|
||||
<field id="description" xsi:type="AttributeText">
|
||||
<sql>description</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
</field>
|
||||
<field id="org_id" xsi:type="AttributeExternalKey">
|
||||
<sql>org_id</sql>
|
||||
<target_class>Organization</target_class>
|
||||
<is_null_allowed>false</is_null_allowed>
|
||||
<on_target_delete>DEL_MANUAL</on_target_delete>
|
||||
</field>
|
||||
<field id="organization_name" xsi:type="AttributeExternalField">
|
||||
<extkey_attcode>org_id</extkey_attcode>
|
||||
<target_attcode>name</target_attcode>
|
||||
</field>
|
||||
<field id="slts_list" xsi:type="AttributeLinkedSetIndirect">
|
||||
<linked_class>lnkSLAToSLT</linked_class>
|
||||
<ext_key_to_me>sla_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<ext_key_to_remote>slt_id</ext_key_to_remote>
|
||||
<duplicates/>
|
||||
</field>
|
||||
<field id="customercontracts_list" xsi:type="AttributeLinkedSet">
|
||||
<linked_class>lnkCustomerContractToService</linked_class>
|
||||
<ext_key_to_me>sla_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<edit_mode>none</edit_mode>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="slts_list">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="customercontracts_list">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="slts_list">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="customercontracts_list">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<default_search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="description">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
</items>
|
||||
</default_search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="org_id">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="SLT" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
@@ -1748,83 +1728,110 @@ public function PrefillSearchForm(&$aContextParam)
|
||||
<values>
|
||||
<value id="hours">
|
||||
<code>hours</code>
|
||||
</value>
|
||||
<value id="minutes">
|
||||
<code>minutes</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>unit</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<display_style>radio_horizontal</display_style>
|
||||
</field>
|
||||
</fields>
|
||||
</value>
|
||||
<value id="minutes">
|
||||
<code>minutes</code>
|
||||
</value>
|
||||
</values>
|
||||
<sql>unit</sql>
|
||||
<default_value/>
|
||||
<is_null_allowed>true</is_null_allowed>
|
||||
<display_style>radio_horizontal</display_style>
|
||||
</field>
|
||||
<field id="slas_list" xsi:type="AttributeLinkedSetIndirect">
|
||||
<linked_class>lnkSLAToSLT</linked_class>
|
||||
<ext_key_to_me>slt_id</ext_key_to_me>
|
||||
<count_min>0</count_min>
|
||||
<count_max>0</count_max>
|
||||
<ext_key_to_remote>sla_id</ext_key_to_remote>
|
||||
<duplicates/>
|
||||
</field>
|
||||
</fields>
|
||||
<methods/>
|
||||
<presentation>
|
||||
<details>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="priority">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="value">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="unit">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="priority">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="value">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="unit">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="priority">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="value">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="unit">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
</item>
|
||||
<item id="priority">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="value">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="unit">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
<item id="slas_list">
|
||||
<rank>100</rank>
|
||||
</item>
|
||||
</items>
|
||||
</details>
|
||||
<search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="priority">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="value">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
<item id="unit">
|
||||
<rank>60</rank>
|
||||
</item>
|
||||
</items>
|
||||
</search>
|
||||
<default_search>
|
||||
<items>
|
||||
<item id="name">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="priority">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
</items>
|
||||
</default_search>
|
||||
<list>
|
||||
<items>
|
||||
<item id="priority">
|
||||
<rank>10</rank>
|
||||
</item>
|
||||
<item id="request_type">
|
||||
<rank>20</rank>
|
||||
</item>
|
||||
<item id="metric">
|
||||
<rank>30</rank>
|
||||
</item>
|
||||
<item id="value">
|
||||
<rank>40</rank>
|
||||
</item>
|
||||
<item id="unit">
|
||||
<rank>50</rank>
|
||||
</item>
|
||||
</items>
|
||||
</list>
|
||||
</presentation>
|
||||
</class>
|
||||
<class id="lnkSLAToSLT" _delta="define">
|
||||
<parent>cmdbAbstractObject</parent>
|
||||
|
||||
@@ -341,7 +341,7 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:SLA/Attribute:slts_list' => 'SLTs',
|
||||
'Class:SLA/Attribute:slts_list+' => 'All the service level targets for this SLA',
|
||||
'Class:SLA/Attribute:customercontracts_list' => 'Customer contracts',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => 'All the customer contracts using this SLA',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => 'All the customer contracted services using this SLA',
|
||||
'Class:SLA/Error:UniqueLnkCustomerContractToService' => 'Could not save link with Customer contract %1$s and service %2$s : SLA already exists',
|
||||
));
|
||||
|
||||
@@ -384,6 +384,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'Class:SLT/Attribute:unit/Value:hours+' => 'hours',
|
||||
'Class:SLT/Attribute:unit/Value:minutes' => 'minutes',
|
||||
'Class:SLT/Attribute:unit/Value:minutes+' => 'minutes',
|
||||
'Class:SLT/Attribute:slas_list' => 'SLAs',
|
||||
'Class:SLT/Attribute:slas_list+' => 'All the service level agreements using this SLT',
|
||||
));
|
||||
|
||||
//
|
||||
|
||||
@@ -331,7 +331,7 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:SLA/Attribute:slts_list' => 'SLTs',
|
||||
'Class:SLA/Attribute:slts_list+' => '',
|
||||
'Class:SLA/Attribute:customercontracts_list' => 'Contrats clients',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => '',
|
||||
'Class:SLA/Attribute:customercontracts_list+' => 'Services contractés par des clients avec ce niveau de service',
|
||||
'Class:SLA/Error:UniqueLnkCustomerContractToService' => 'Impossible de sauvegarder le lien avec le contrat client %1$s et le service %2$s : un SLA existe déjà.',
|
||||
));
|
||||
|
||||
@@ -374,6 +374,8 @@ Dict::Add('FR FR', 'French', 'Français', array(
|
||||
'Class:SLT/Attribute:unit/Value:hours+' => 'heures',
|
||||
'Class:SLT/Attribute:unit/Value:minutes' => 'minutes',
|
||||
'Class:SLT/Attribute:unit/Value:minutes+' => 'minutes',
|
||||
'Class:SLT/Attribute:slas_list' => 'SLAs',
|
||||
'Class:SLT/Attribute:slas_list+' => 'Tous les niveaux de service utilisant cet objectif',
|
||||
));
|
||||
|
||||
//
|
||||
|
||||
@@ -1873,6 +1873,14 @@
|
||||
<precompiled_stylesheet>itop-structure/precompiled-themes/test-red/main.css</precompiled_stylesheet>
|
||||
</theme>
|
||||
</themes>
|
||||
<themes_common>
|
||||
<variables>
|
||||
</variables>
|
||||
<imports>
|
||||
</imports>
|
||||
<stylesheets>
|
||||
</stylesheets>
|
||||
</themes_common>
|
||||
</branding>
|
||||
<user_rights>
|
||||
<groups>
|
||||
|
||||
Reference in New Issue
Block a user