mirror of
https://github.com/Combodo/iTop.git
synced 2026-04-24 11:08:45 +02:00
Merge remote-tracking branch 'origin/support/3.2' into develop
This commit is contained in:
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
@@ -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');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -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.',
|
||||||
|
|||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
102
tests/php-unit-tests/unitary-tests/core/RelationGraphTest.php
Normal file
102
tests/php-unit-tests/unitary-tests/core/RelationGraphTest.php
Normal 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.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user