mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
N°7216 import improves error handling missing or null data (#612)
Co-authored-by: Thomas Casteleyn <thomas.casteleyn@super-visions.com>
This commit is contained in:
@@ -519,7 +519,7 @@ class BulkChange
|
||||
foreach ($this->m_aExtKeys[$sAttCode] as $sForeignAttCode => $iCol)
|
||||
{
|
||||
// The foreign attribute is one of our reconciliation key
|
||||
if (strlen($aRowData[$iCol]) > 0)
|
||||
if (isset($aRowData[$iCol]) && strlen($aRowData[$iCol]) > 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -1181,6 +1181,9 @@ class BulkChange
|
||||
foreach($this->m_aData as $iRow => $aRowData)
|
||||
{
|
||||
$sFormat = $sDateTimeFormat;
|
||||
if(!isset($this->m_aData[$iRow][$iCol])){
|
||||
continue;
|
||||
}
|
||||
$sValue = $this->m_aData[$iRow][$iCol];
|
||||
if (!empty($sValue))
|
||||
{
|
||||
@@ -1233,11 +1236,19 @@ class BulkChange
|
||||
$iPreviousTimeLimit = ini_get('max_execution_time');
|
||||
$iLoopTimeLimit = MetaModel::GetConfig()->Get('max_execution_time_per_loop');
|
||||
|
||||
$iNBFields = count($this->m_aAttList) + count($this->m_aExtKeys);
|
||||
|
||||
// Avoid too many events
|
||||
cmdbAbstractObject::SetEventDBLinksChangedBlocked(true);
|
||||
try {
|
||||
foreach ($this->m_aData as $iRow => $aRowData) {
|
||||
set_time_limit(intval($iLoopTimeLimit));
|
||||
// Stop if not the good number of cols in $aRowData
|
||||
if(count($aRowData) != $iNBFields){
|
||||
$aResult[$iRow]["__STATUS__"] = new RowStatus_Issue(Dict::Format('UI:CSVReport-Row-Issue-NbField',count($aRowData),$iNBFields) );
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isset($aResult[$iRow]["__STATUS__"])) {
|
||||
// An issue at the earlier steps - skip the rest
|
||||
continue;
|
||||
@@ -1348,7 +1359,11 @@ class BulkChange
|
||||
{
|
||||
if (!array_key_exists($iCol, $aResult[$iRow]))
|
||||
{
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
if(isset($aRowData[$iCol])) {
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
} else {
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue('', null, Dict::S('UI:CSVReport-Value-Issue-NoValue'));
|
||||
}
|
||||
}
|
||||
}
|
||||
foreach($this->m_aExtKeys as $sAttCode => $aForeignAtts)
|
||||
@@ -1362,7 +1377,11 @@ class BulkChange
|
||||
if (!array_key_exists($iCol, $aResult[$iRow]))
|
||||
{
|
||||
// The foreign attribute is one of our reconciliation key
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
if(isset($aRowData[$iCol])) {
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Void($aRowData[$iCol]);
|
||||
} else {
|
||||
$aResult[$iRow][$iCol] = new CellStatus_Issue('', null, 'UI:CSVReport-Value-Issue-NoValue');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -719,6 +719,8 @@ Dict::Add('EN US', 'English', 'English', array(
|
||||
'UI:CSVReport-Row-Issue-Reconciliation' => 'failed to reconcile',
|
||||
'UI:CSVReport-Row-Issue-Ambiguous' => 'ambiguous reconciliation',
|
||||
'UI:CSVReport-Row-Issue-Internal' => 'Internal error: %1$s, %2$s',
|
||||
'UI:CSVReport-Value-Issue-NoValue' => 'No value',
|
||||
'UI:CSVReport-Row-Issue-NbField' => 'Not the expected number of columns (found: %1$s, expected: %2$s)',
|
||||
|
||||
'UI:CSVReport-Icon-Unchanged' => 'Unchanged',
|
||||
'UI:CSVReport-Icon-Modified' => 'Modified',
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
*
|
||||
* @copyright Copyright (C) 2010-2024 Combodo SAS
|
||||
* @license https://opensource.org/licenses/AGPL-3.0
|
||||
*
|
||||
*
|
||||
*/
|
||||
/**
|
||||
*
|
||||
@@ -678,6 +678,8 @@ Elle s\'applique à tous les objets dans le périmètre de sa catégorie d\'audi
|
||||
'UI:CSVReport-Row-Issue-ExpectedDateFormat' => 'Expected format: %1$s~~',
|
||||
'UI:CSVReport-Row-Issue-Inconsistent' => 'Incohérence entre attributs: %1$s',
|
||||
'UI:CSVReport-Row-Issue-Internal' => 'Erreur interne: %1$s, %2$s',
|
||||
'UI:CSVReport-Value-Issue-NoValue' => 'Pas de valeur',
|
||||
'UI:CSVReport-Row-Issue-NbField' => 'Le nombre de colonnes ne correspond pas à ce qui est attendu (constaté : %1$s, attendu : %2$s)',
|
||||
'UI:CSVReport-Row-Issue-MissingExtKey' => 'Ne peut pas être créé car il manque des clés externes : %1$s',
|
||||
'UI:CSVReport-Row-Issue-Reconciliation' => 'Echec de réconciliation',
|
||||
'UI:CSVReport-Row-Unchanged' => 'inchangé',
|
||||
|
||||
@@ -345,7 +345,7 @@ try
|
||||
$oPanel->AddSubBlock($oTable);
|
||||
|
||||
$oPage->AddSubBlock($oPanel);
|
||||
if (empty($sInitSearchField)) {
|
||||
if (empty($sInitSearchField) || empty($aInitFieldMapping)) {
|
||||
// Propose a reconciliation scheme
|
||||
//
|
||||
$aReconciliationKeys = MetaModel::GetReconcKeys($sClassName);
|
||||
|
||||
@@ -222,30 +222,36 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
* @param $aExtKeys
|
||||
* @param $aReconcilKeys
|
||||
*/
|
||||
public function testBulkChangeWithExistingData($aInitData, $aCsvData, $aAttributes, $aExtKeys, $aReconcilKeys, $aResult, $aResultHTML= null) {
|
||||
public function testBulkChangeWithExistingData($aInitData, $aCsvData, $aAttributes, $aExtKeys, $aReconcilKeys, $aResult, $aResultHTML= null ) {
|
||||
//change value during the test
|
||||
$db_core_transactions_enabled=MetaModel::GetConfig()->Get('db_core_transactions_enabled');
|
||||
MetaModel::GetConfig()->Set('db_core_transactions_enabled',false);
|
||||
|
||||
|
||||
if (is_array($aInitData) && sizeof($aInitData) != 0) {
|
||||
/** @var Server $oServer */
|
||||
$oServer = $this->createObject('Server', array(
|
||||
'name' => $aInitData[1],
|
||||
'status' => $aInitData[2],
|
||||
'org_id' => $aInitData[0],
|
||||
'name' => $aInitData[1],
|
||||
'status' => $aInitData[2],
|
||||
'org_id' => $aInitData[0],
|
||||
'purchase_date' => $aInitData[3],
|
||||
));
|
||||
$aCsvData[0][2]=$oServer->GetKey();
|
||||
$aResult[2]=$oServer->GetKey();
|
||||
if ($aResult["id"]==="{Id of the server created by the test}") {
|
||||
$aResult["id"]=$oServer->GetKey();
|
||||
if ($aResultHTML!==null){
|
||||
$aResultHTML[2]=$oServer->GetKey();
|
||||
$aResultHTML["id"]=$oServer->GetKey();
|
||||
if(array_key_exists('id', $aAttributes)) {
|
||||
$iColumnForId = $aAttributes['id'];
|
||||
$aCsvData[0][$iColumnForId] = $oServer->GetKey();
|
||||
$aResult[$iColumnForId] = $oServer->GetKey();
|
||||
if ($aResult["id"] === "{Id of the server created by the test}") {
|
||||
$aResult["id"] = $oServer->GetKey();
|
||||
if ($aResultHTML !== null) {
|
||||
$aResultHTML[$iColumnForId] = $oServer->GetKey();
|
||||
$aResultHTML["id"] = $oServer->GetKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->debug("oServer->GetKey():".$oServer->GetKey());
|
||||
}
|
||||
|
||||
|
||||
$oBulk = new BulkChange(
|
||||
"Server",
|
||||
$aCsvData,
|
||||
@@ -270,7 +276,7 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
$this->debug('GetCLIValue:'.$oCell->GetCLIValue());
|
||||
$this->debug("aResult:".$aResult[$i]);
|
||||
$this->assertEquals( $aResult[$i], $oCell->GetCLIValue(), "failure on " . get_class($oCell) . ' cell type for cell number ' . $i );
|
||||
if (null !== $aResultHTML) {
|
||||
if (null !== $aResultHTML && array_key_exists($i, $aResultHTML)) {
|
||||
$this->assertEquals($aResultHTML[$i], $oCell->GetHTMLValue(), "failure on " . get_class($oCell) . ' cell type for cell number ' . $i);
|
||||
}
|
||||
} else if ($i === "__ERRORS__") {
|
||||
@@ -294,37 +300,39 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
["1", "Server1", "production", ""],
|
||||
"csvData" =>
|
||||
[[">Demo", "Server1"]],
|
||||
"attributes"=>
|
||||
["name" => 1],
|
||||
"extKeys"=>
|
||||
["org_id" => ["name" => 0]],
|
||||
"reconcilKeys"=>
|
||||
["name"],
|
||||
"expectedResult"=>
|
||||
[
|
||||
0 => ">Demo",
|
||||
"org_id" => "n/a",
|
||||
1 => "Server1",
|
||||
"id" => "Invalid value for attribute",
|
||||
"__STATUS__" => "Issue: ambiguous reconciliation",
|
||||
"__ERRORS__" => "Allowed 'status' value(s): stock,implementation,production,obsolete",
|
||||
],
|
||||
"attributes"=>
|
||||
["name" => 1],
|
||||
"extKeys"=>
|
||||
["org_id" => ["name" => 0]],
|
||||
"reconcilKeys"=>
|
||||
["name"],
|
||||
"expectedResult"=>
|
||||
[
|
||||
0 => ">Demo",
|
||||
"org_id" => "n/a",
|
||||
1 => "Server1",
|
||||
"id" => "Invalid value for attribute",
|
||||
"name" => "Invalid value for attribute",
|
||||
"__STATUS__" => "Issue: ambiguous reconciliation",
|
||||
"__ERRORS__" => "Object not found",
|
||||
],
|
||||
"expectedResultHTML"=>
|
||||
[
|
||||
0 => ">Demo",
|
||||
"org_id" => "n/a",
|
||||
1 => "Server1",
|
||||
"id" => "Invalid value for attribute",
|
||||
"name" => "Invalid value for attribute",
|
||||
"__STATUS__" => "Issue: ambiguous reconciliation",
|
||||
"__ERRORS__" => "Allowed 'status' value(s): stock,implementation,production,obsolete",
|
||||
"__ERRORS__" => "Object not found",
|
||||
],
|
||||
],
|
||||
"Case 6 - 1 : Unexpected value (update)" => [
|
||||
"initData"=>
|
||||
["1", ">ServerTest", "production", ""],
|
||||
"csvData"=>
|
||||
"csvData"=>
|
||||
[["Demo", ">ServerTest", "key - will be automatically overwritten by test", ">BadValue", ""]],
|
||||
"attributes"=>
|
||||
"attributes"=>
|
||||
["name" => 1, "id" => 2, "status" => 3, "purchase_date" => 4],
|
||||
"extKeys"=>
|
||||
["org_id" => ["name" => 0]],
|
||||
@@ -354,7 +362,6 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
"__STATUS__" => "Issue: Unexpected attribute value(s)",
|
||||
"__ERRORS__" => "Allowed 'status' value(s): stock,implementation,production,obsolete",
|
||||
],
|
||||
|
||||
],
|
||||
"Case 6 - 2 : Unexpected value (update)" => [
|
||||
"initData"=>
|
||||
@@ -396,9 +403,9 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
"initData"=>
|
||||
[],
|
||||
"csvData"=>
|
||||
[["Demo", ">ServerTest", "<svg onclick\"alert(1)\">", ""]],
|
||||
[["Demo", ">ServerTest", "<svg onclick\"alert(1)\">", 1]],
|
||||
"attributes"=>
|
||||
["name" => 1, "status" => 2, "purchase_date" => 3],
|
||||
["name" => 1, "status" => 2, 'id'=> 3],
|
||||
"extKeys"=>
|
||||
["org_id" => ["name" => 0]],
|
||||
"reconcilKeys"=>
|
||||
@@ -410,7 +417,7 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
"org_id" => "3",
|
||||
1 => "\">ServerTest\"",
|
||||
2 => '\'<svg onclick"alert(1)">\' is an invalid value',
|
||||
3 => "",
|
||||
3 => "1",
|
||||
"__STATUS__" => "Issue: Unexpected attribute value(s)",
|
||||
"__ERRORS__" => "Allowed 'status' value(s): stock,implementation,production,obsolete",
|
||||
],
|
||||
@@ -421,7 +428,7 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
"org_id" => "3",
|
||||
1 => ">ServerTest",
|
||||
2 => "'<svg onclick"alert(1)">' is an invalid value",
|
||||
3 => "",
|
||||
3 => "1",
|
||||
"__STATUS__" => "Issue: Unexpected attribute value(s)",
|
||||
"__ERRORS__" => "Allowed 'status' value(s): stock,implementation,production,obsolete",
|
||||
],
|
||||
@@ -580,11 +587,52 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
[ "id" => "{Id of the server created by the test}",
|
||||
0 => "Demo", "org_id" => "n/a", 1 => ">ServerTest", 2 => "1", 3 => "production", 4 => "'2020-20-03' is an invalid value", "id" => 1, "__STATUS__" => "Issue: wrong date format"],
|
||||
],
|
||||
"Case 11 : Missing AttributeDateTime cell should issue an error" => [
|
||||
"initData"=>
|
||||
["1", "ServerTest", "production", "2020-02-01"],
|
||||
"csvData"=>
|
||||
[["1"]],
|
||||
"attributes"=>
|
||||
["id" => 0,"purchase_date" => 1],
|
||||
"extKeys"=>
|
||||
[],
|
||||
"reconcilKeys"=>
|
||||
["id"],
|
||||
"expectedResult"=>
|
||||
[ 1 => "'' is an invalid value", "id" => 1, "__STATUS__" => 'Issue: Not the expected number of columns (found: 1, expected: 2)'],
|
||||
],
|
||||
"Case 12 : Missing AttributeEnum cell should issue an error" => [
|
||||
"initData"=>
|
||||
["1", "ServerTest", "production", "2020-02-01"],
|
||||
"csvData"=>
|
||||
[[ "1"]], // missing status
|
||||
"attributes"=>
|
||||
[ "id" => 0, "status" => 1],
|
||||
"extKeys"=>
|
||||
[],
|
||||
"reconcilKeys"=>
|
||||
["id"],
|
||||
"expectedResult"=>
|
||||
[ 1 => "'' is an invalid value", "id" => 1, "__STATUS__" => 'Issue: Not the expected number of columns (found: 1, expected: 2)'],
|
||||
],
|
||||
"Case 13 : Missing AttributeExternalKey cell should issue an error" => [
|
||||
"initData"=>
|
||||
["1", "ServerTest", "production", "2020-02-01"],
|
||||
"csvData"=>
|
||||
[[ "1"]], // missing org_id
|
||||
"attributes"=>
|
||||
[ "id" => 0],
|
||||
"extKeys"=>
|
||||
["org_id" => ["name" => 1]],
|
||||
"reconcilKeys"=>
|
||||
["id"],
|
||||
"expectedResult"=>
|
||||
[ 1 => "'' is an invalid value", "id" => 1, "__STATUS__" => 'Issue: Not the expected number of columns (found: 1, expected: 2)'],
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* test $oBulk->Process with new server and new organization datas
|
||||
*
|
||||
@@ -618,7 +666,7 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
'org_id' => $oOrganisation->GetKey(),
|
||||
'purchase_date' => $aInitData["serverPurchaseDate"],
|
||||
));
|
||||
$aCsvData[0][2]=$oServer->GetKey();
|
||||
$aCsvData[0][2] = $oServer->GetKey();
|
||||
$aResult[2]=$oServer->GetKey();
|
||||
if ($aResult["id"]==="{Id of the server created by the test}") {
|
||||
$aResult["id"]=$oServer->GetKey();
|
||||
@@ -648,7 +696,7 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
$this->debug('GetCLIValue:'.$oCell->GetCLIValue());
|
||||
$this->debug("aResult:".$aResult[$i]);
|
||||
$this->assertEquals($aResult[$i], $oCell->GetCLIValue(), "$i cell is incorrect");
|
||||
if (null !== $aResultHTML) {
|
||||
if (null !== $aResultHTML && array_key_exists($i, $aResultHTML)) {
|
||||
$this->assertEquals($aResultHTML[$i], $oCell->GetHTMLValue());
|
||||
}
|
||||
} elseif ($i === "__STATUS__") {
|
||||
@@ -675,7 +723,7 @@ class BulkChangeTest extends ItopDataTestCase
|
||||
"csvData" =>
|
||||
[["Demo", ">Server1"]],
|
||||
"attributes"=>
|
||||
["name" => 1],
|
||||
["name" => 1,"id" => 2],
|
||||
"extKeys"=>
|
||||
["org_id" => ["name" => 0]],
|
||||
"reconcilKeys"=>
|
||||
|
||||
@@ -183,11 +183,11 @@ class BulkChangeExtKeyTest extends ItopDataTestCase {
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'Found 2 matches'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @dataProvider ReconciliationKeyProvider
|
||||
*/
|
||||
@@ -209,6 +209,7 @@ class BulkChangeExtKeyTest extends ItopDataTestCase {
|
||||
null,
|
||||
$bIsRackReconKey,
|
||||
$aCsvData,
|
||||
['description'=>3],
|
||||
$aExtKeys,
|
||||
$sSearchLinkUrl
|
||||
);
|
||||
@@ -224,7 +225,7 @@ class BulkChangeExtKeyTest extends ItopDataTestCase {
|
||||
}
|
||||
|
||||
public function performBulkChangeTest($sExpectedDisplayableValue, $sExpectedDescription, $oOrg, $bIsRackReconKey,
|
||||
$aAdditionalCsvData=null, $aExtKeys=null, $sSearchLinkUrl=null, $sError="Object not found") {
|
||||
$aAdditionalCsvData=null, $aAdditionalAttributes=null, $aExtKeys=null, $sSearchLinkUrl=null, $sError="Object not found") {
|
||||
if ($sSearchLinkUrl===null){
|
||||
$sSearchLinkUrl = 'UI.php?operation=search&filter='.rawurlencode('%5B%22SELECT+%60Rack%60+FROM+Rack+AS+%60Rack%60+WHERE+%28%60Rack%60.%60name%60+%3D+%3Aname%29%22%2C%7B%22name%22%3A%22UnexistingRack%22%7D%2C%5B%5D%5D');
|
||||
}
|
||||
@@ -247,6 +248,9 @@ class BulkChangeExtKeyTest extends ItopDataTestCase {
|
||||
}
|
||||
}
|
||||
$aAttributes = ["name" => 2];
|
||||
if ($aAdditionalAttributes !== null){
|
||||
$aAttributes = array_merge($aAttributes, $aAdditionalAttributes);
|
||||
}
|
||||
if ($aExtKeys == null){
|
||||
$aExtKeys = ["org_id" => ["name" => 0], "rack_id" => ["name" => 1]];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user