Merge remote-tracking branch 'origin/support/3.2' into develop

This commit is contained in:
Benjamin Dalsass
2024-04-17 16:05:56 +02:00
6 changed files with 212 additions and 29 deletions

View File

@@ -2609,6 +2609,13 @@ JS
$iFieldSize = $oAttDef->GetMaxSize(); $iFieldSize = $oAttDef->GetMaxSize();
if ($aAllowedValues !== null) if ($aAllowedValues !== null)
{ {
// convert AttributeBoolean value due to issue with radio style when value is false
// @see N°2443 - Boolean don't accept yes/no value
if($oAttDef instanceof AttributeBoolean){
$value = $value === false ? 0 : 1;
}
// Discrete list of values, use a SELECT or RADIO buttons depending on the config // Discrete list of values, use a SELECT or RADIO buttons depending on the config
$sDisplayStyle = $oAttDef->GetDisplayStyle(); $sDisplayStyle = $oAttDef->GetDisplayStyle();
switch ($sDisplayStyle) switch ($sDisplayStyle)

View File

@@ -2226,8 +2226,8 @@ SQL;
$fScale = min($iMaxImageWidth / $iWidth, $iMaxImageHeight / $iHeight); $fScale = min($iMaxImageWidth / $iWidth, $iMaxImageHeight / $iHeight);
$iNewWidth = $iWidth * $fScale; $iNewWidth = floor($iWidth * $fScale);
$iNewHeight = $iHeight * $fScale; $iNewHeight = floor($iHeight * $fScale);
$new = imagecreatetruecolor($iNewWidth, $iNewHeight); $new = imagecreatetruecolor($iNewWidth, $iNewHeight);

View File

@@ -3572,6 +3572,19 @@ class AttributeBoolean extends AttributeInteger
{ {
return CMDBChangeOpSetAttributeScalar::class; return CMDBChangeOpSetAttributeScalar::class;
} }
public function GetAllowedValues($aArgs = array(), $sContains = '') : array
{
return [
0 => $this->GetValueLabel(false),
1 => $this->GetValueLabel(true)
];
}
public function GetDisplayStyle()
{
return $this->GetOptional('display_style', 'select');
}
} }
/** /**

View File

@@ -1209,6 +1209,14 @@ class Config
'source_of_value' => '', 'source_of_value' => '',
'show_in_conf_sample' => false, 'show_in_conf_sample' => false,
], ],
'relations.complete_analysis' => [
'type' => 'bool',
'description' => 'Continue the impact/depends analysis even if a step is not visible to the user',
'default' => false,
'value' => '',
'source_of_value' => '',
'show_in_conf_sample' => false,
],
'sessions_tracking.enabled' => [ 'sessions_tracking.enabled' => [
'type' => 'bool', 'type' => 'bool',
'description' => 'Whether or not the whole mechanism to track active sessions is enabled. See PHP session.gc_maxlifetime setting to configure session expiration.', 'description' => 'Whether or not the whole mechanism to track active sessions is enabled. See PHP session.gc_maxlifetime setting to configure session expiration.',

View File

@@ -20,7 +20,7 @@
/** /**
* Data structures (i.e. PHP classes) to build and use relation graphs * Data structures (i.e. PHP classes) to build and use relation graphs
* *
* @copyright Copyright (C) 2015-2023 Combodo SARL * @copyright Copyright (C) 2015-2024 Combodo SARL
* @license http://opensource.org/licenses/AGPL-3.0 * @license http://opensource.org/licenses/AGPL-3.0
* *
*/ */
@@ -367,6 +367,9 @@ class RelationGraph extends SimpleGraph
$oNode->ReachDown('is_reached', true); $oNode->ReachDown('is_reached', true);
} }
} }
if ( MetaModel::GetConfig()->Get('relations.complete_analysis')) {
$this->ApplyUserRightsOnGraph();
}
} }
/** /**
@@ -401,6 +404,9 @@ class RelationGraph extends SimpleGraph
$oNode->ReachDown('is_reached', true); $oNode->ReachDown('is_reached', true);
} }
} }
if ( MetaModel::GetConfig()->Get('relations.complete_analysis')) {
$this->ApplyUserRightsOnGraph();
}
} }
@@ -460,6 +466,10 @@ class RelationGraph extends SimpleGraph
try try
{ {
$oFlt = static::MakeSearch($sQuery); $oFlt = static::MakeSearch($sQuery);
if ( MetaModel::GetConfig()->Get('relations.complete_analysis')) {
//no filter to find all impacts
$oFlt->AllowAllData(true);
}
$oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery()); $oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery());
$oRelatedObj = $oObjSet->Fetch(); $oRelatedObj = $oObjSet->Fetch();
} }
@@ -474,27 +484,24 @@ class RelationGraph extends SimpleGraph
{ {
set_time_limit(intval($iLoopTimeLimit)); set_time_limit(intval($iLoopTimeLimit));
$sObjectRef = RelationObjectNode::MakeId($oRelatedObj); $sObjectRef = RelationObjectNode::MakeId($oRelatedObj);
$oRelatedNode = $this->GetNode($sObjectRef); $oRelatedNode = $this->GetNode($sObjectRef);
if (is_null($oRelatedNode)) if (is_null($oRelatedNode)) {
{ $oRelatedNode = new RelationObjectNode($this, $oRelatedObj);
$oRelatedNode = new RelationObjectNode($this, $oRelatedObj); }
} $oSourceNode = $bDown ? $oObjectNode : $oRelatedNode;
$oSourceNode = $bDown ? $oObjectNode : $oRelatedNode; $oSinkNode = $bDown ? $oRelatedNode : $oObjectNode;
$oSinkNode = $bDown ? $oRelatedNode : $oObjectNode;
if ($bEnableRedundancy) if ($bEnableRedundancy)
{ {
$oRedundancyNode = $this->ComputeRedundancy($sRelCode, $aQueryInfo, $oSourceNode, $oSinkNode); $oRedundancyNode = $this->ComputeRedundancy($sRelCode, $aQueryInfo, $oSourceNode, $oSinkNode);
} } else {
else $oRedundancyNode = null;
{ }
$oRedundancyNode = null; if (!$oRedundancyNode) {
} // Direct link (otherwise handled by ComputeRedundancy)
if (!$oRedundancyNode) new RelationEdge($this, $oSourceNode, $oSinkNode);
{ }
// Direct link (otherwise handled by ComputeRedundancy)
new RelationEdge($this, $oSourceNode, $oSinkNode);
}
// Recurse // Recurse
$this->AddRelatedObjects($sRelCode, $bDown, $oRelatedNode, $iMaxDepth - 1, $bEnableRedundancy); $this->AddRelatedObjects($sRelCode, $bDown, $oRelatedNode, $iMaxDepth - 1, $bEnableRedundancy);
} }
@@ -538,6 +545,10 @@ class RelationGraph extends SimpleGraph
try try
{ {
$oFlt = static::MakeSearch($sQuery); $oFlt = static::MakeSearch($sQuery);
if ( MetaModel::GetConfig()->Get('relations.complete_analysis')) {
//no filter to find all impacts
$oFlt->AllowAllData(true);
}
$oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery()); $oObjSet = new DBObjectSet($oFlt, array(), $oObject->ToArgsForQuery());
$iCount = $oObjSet->Count(); $iCount = $oObjSet->Count();
} }
@@ -553,13 +564,12 @@ class RelationGraph extends SimpleGraph
while ($oUpperObj = $oObjSet->Fetch()) while ($oUpperObj = $oObjSet->Fetch())
{ {
$sObjectRef = RelationObjectNode::MakeId($oUpperObj); $sObjectRef = RelationObjectNode::MakeId($oUpperObj);
$oUpperNode = $this->GetNode($sObjectRef); $oUpperNode = $this->GetNode($sObjectRef);
if (is_null($oUpperNode)) if (is_null($oUpperNode)) {
{ $oUpperNode = new RelationObjectNode($this, $oUpperObj);
$oUpperNode = new RelationObjectNode($this, $oUpperObj); }
} new RelationEdge($this, $oUpperNode, $oRedundancyNode);
new RelationEdge($this, $oUpperNode, $oRedundancyNode);
} }
} }
} }
@@ -694,4 +704,47 @@ class RelationGraph extends SimpleGraph
$oSearch->SetArchiveMode(false); $oSearch->SetArchiveMode(false);
return $oSearch; return $oSearch;
} }
/**
* @return void
* @throws \CoreException
* @throws \CoreUnexpectedValue
* @throws \MySQLException
* @throws \OQLException
* @throws \SimpleGraphException
*/
private function ApplyUserRightsOnGraph()
{
//The chart is complete. Now we need to control which objects are allowed to the current user.
if (!UserRights::IsAdministrator()) {
//First we get all the objects presents in chart in $aArrayTest
$oIterator = new RelationTypeIterator($this, 'Node');
$aArrayTest = [];
foreach ($oIterator as $oNode) {
$oObj = $oNode->GetProperty('object');
if ($oObj) {
$aArrayTest[get_class($oObj)][$oObj->GetKey()] = $oObj->GetKey();
}
}
//Then for each class, we made a request to control access rights
// visible objects are removed from $aArrayTest
foreach ($aArrayTest as $sClass => $aKeys) {
$sOQL = "SELECT ".$sClass.' WHERE id IN ('.implode(',', $aKeys).')';
$oSearch = DBObjectSearch::FromOQL($sOQL);
$aListId = $oSearch->SelectAttributeToArray('id');
foreach($aListId as$aItem ) {
unset($aArrayTest[$sClass][$aItem['id']]);
}
}
//then removes from the graph all objects still present in $aArrayTest
foreach ($oIterator as $oNode) {
$oObj = $oNode->GetProperty('object');
if ($oObj && isset($aArrayTest[get_class($oObj)]) && in_array($oObj->GetKey(), $aArrayTest[get_class($oObj)])) {
$this->FilterNode($oNode);
}
}
}
}
} }

View File

@@ -0,0 +1,102 @@
<?php
namespace Combodo\iTop\Test\UnitTest\Core;
use Combodo\iTop\Test\UnitTest\ItopDataTestCase;
use MetaModel;
use RelationGraph;
/**
* Class RelationGraphTest
*
* @package Combodo\iTop\Test\UnitTest\Core
*/
class RelationGraphTest extends ItopDataTestCase
{
const USE_TRANSACTION = false;
protected function setUp(): void
{
parent::setUp();
}
public function ComputeRelatedObjectsProvider()
{
return array(
'Server::1' => array('Server',1),
'Server::2' => array('Server',2),
);
}
/**
* @dataProvider ComputeRelatedObjectsProvider
*
* @param $sClass
* @param $iKey
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function testComputeRelatedObjectsDown($sClass, $iKey)
{
$oServer = MetaModel::GetObject($sClass, $iKey);
MetaModel::GetConfig()->Set('relations.complete_analysis', true);
$oGraphTrue = new RelationGraph();
$oGraphTrue->AddSourceObject($oServer);
$oGraphTrue->ComputeRelatedObjectsDown('impacts', 10, true);
MetaModel::GetConfig()->Set('relations.complete_analysis', false);
$oGraphFalse = new RelationGraph();
$oGraphFalse->AddSourceObject($oServer);
$oGraphFalse->ComputeRelatedObjectsDown('impacts', 10, true);
$aNodeFalse = $oGraphFalse->_GetNodes();
$aNodeTrue = $oGraphFalse->_GetNodes();
//test if the 2 graph contains the same objects
$this->assertEquals(count($aNodeFalse), count($aNodeFalse),'With the admin user, the impact analysis down must have the same number of impacted items whatever the value of the "relations.complete_analysis" parameter.');
foreach ($aNodeTrue as $sKey =>$oNodeTrue){
$this->assertArrayHasKey($sKey, $aNodeFalse,'With the admin user, the impact analysis down must have the same results whatever the value of the "relations.complete_analysis" parameter.');
}
}
/**
* @dataProvider ComputeRelatedObjectsProvider
*
* @param $sClass
* @param $iKey
*
* @return void
* @throws \ArchivedObjectException
* @throws \CoreException
*/
public function testComputeRelatedObjectsUp($sClass, $iKey)
{
$oServer = MetaModel::GetObject($sClass, $iKey);
MetaModel::GetConfig()->Set('relations.complete_analysis', true);
$oGraphTrue = new RelationGraph();
$oGraphTrue->AddSourceObject($oServer);
$oGraphTrue->ComputeRelatedObjectsUp('impacts', 10, true);
MetaModel::GetConfig()->Set('relations.complete_analysis', false);
$oGraphFalse = new RelationGraph();
$oGraphFalse->AddSourceObject($oServer);
$oGraphFalse->ComputeRelatedObjectsUp('impacts', 10, true);
$aNodeFalse = $oGraphFalse->_GetNodes();
$aNodeTrue = $oGraphFalse->_GetNodes();
//test if the 2 graph contains the same objects
$this->assertEquals(count($aNodeFalse), count($aNodeFalse),'With the admin user, the impact analysis up must have the same number of impacted items whatever the value of the "relations.complete_analysis" parameter.');
foreach ($aNodeTrue as $sKey =>$oNodeTrue){
$this->assertArrayHasKey($sKey, $aNodeFalse,'With the admin user, the impact analysis up must have the same results whatever the value of the "relations.complete_analysis" parameter.');
}
}
}