mirror of
https://github.com/Combodo/iTop.git
synced 2026-02-13 07:24:13 +01:00
#328 Added the capability to import/export link sets in CSV format
SVN:trunk[1129]
This commit is contained in:
@@ -827,6 +827,8 @@ EOF
|
||||
{
|
||||
$sSeparator = isset($aParams['separator']) ? $aParams['separator'] : ','; // default separator is comma
|
||||
$sTextQualifier = isset($aParams['text_qualifier']) ? $aParams['text_qualifier'] : '"'; // default text qualifier is double quote
|
||||
$aFields = isset($aParams['fields']) ? explode(',', $aParams['fields']) : null;
|
||||
|
||||
$aList = array();
|
||||
|
||||
$oAppContext = new ApplicationContext();
|
||||
@@ -845,7 +847,9 @@ EOF
|
||||
{
|
||||
foreach(MetaModel::ListAttributeDefs($sClassName) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ((($oAttDef->IsExternalField()) || ($oAttDef->IsWritable())) && $oAttDef->IsScalar())
|
||||
if (!is_null($aFields) && !in_array($sAttCode, $aFields)) continue;
|
||||
|
||||
if ($oAttDef->IsExternalField() || $oAttDef->IsWritable())
|
||||
{
|
||||
$aList[$sClassName][$sAttCode] = $oAttDef;
|
||||
}
|
||||
@@ -906,7 +910,7 @@ EOF
|
||||
}
|
||||
else
|
||||
{
|
||||
$aRow[] = $oObj->GetAsCSV($sAttCode, $sSeparator, '\\');
|
||||
$aRow[] = $oObj->GetAsCSV($sAttCode, $sSeparator, $sTextQualifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -959,7 +963,7 @@ EOF
|
||||
}
|
||||
else
|
||||
{
|
||||
if (($oAttDef->IsWritable()) && ($oAttDef->IsScalar()))
|
||||
if ($oAttDef->IsWritable())
|
||||
{
|
||||
$sValue = $oObj->GetAsXML($sAttCode);
|
||||
$oPage->add("<$sAttCode>$sValue</$sAttCode>\n");
|
||||
|
||||
@@ -269,17 +269,17 @@ abstract class AttributeDefinition
|
||||
return (string)$sValue;
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2html((string)$sValue);
|
||||
}
|
||||
|
||||
public function GetAsXML($sValue)
|
||||
public function GetAsXML($sValue, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2xml((string)$sValue);
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
return (string)$sValue;
|
||||
}
|
||||
@@ -365,21 +365,188 @@ class AttributeLinkedSet extends AttributeDefinition
|
||||
public function GetBasicFilterLooseOperator() {return '';}
|
||||
public function GetBasicFilterSQLExpr($sOpCode, $value) {return '';}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
return "ERROR: LIST OF OBJECTS";
|
||||
if (is_object($sValue) && ($sValue instanceof DBObjectSet))
|
||||
{
|
||||
$sValue->Rewind();
|
||||
$aItems = array();
|
||||
while ($oObj = $sValue->Fetch())
|
||||
{
|
||||
// Show only relevant information (hide the external key to the current object)
|
||||
$aAttributes = array();
|
||||
foreach(MetaModel::ListAttributeDefs($this->GetLinkedClass()) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($sAttCode == $this->GetExtKeyToMe()) continue;
|
||||
if ($oAttDef->IsExternalField()) continue;
|
||||
$sAttValue = $oObj->GetAsHTML($sAttCode);
|
||||
if (strlen($sAttValue) > 0)
|
||||
{
|
||||
$aAttributes[] = $sAttValue;
|
||||
}
|
||||
}
|
||||
$sAttributes = implode(', ', $aAttributes);
|
||||
$aItems[] = $sAttributes;
|
||||
}
|
||||
return implode('<br/>', $aItems);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public function GetAsXML($sValue)
|
||||
public function GetAsXML($sValue, $oHostObject = null)
|
||||
{
|
||||
return "ERROR: LIST OF OBJECTS";
|
||||
return "Sorry, no yet implemented";
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
return "ERROR: LIST OF OBJECTS";
|
||||
$sSepItem = MetaModel::GetConfig()->Get('link_set_item_separator');
|
||||
$sSepAttribute = MetaModel::GetConfig()->Get('link_set_attribute_separator');
|
||||
$sSepValue = MetaModel::GetConfig()->Get('link_set_value_separator');
|
||||
$sAttributeQualifier = MetaModel::GetConfig()->Get('link_set_attribute_qualifier');
|
||||
|
||||
if (is_object($sValue) && ($sValue instanceof DBObjectSet))
|
||||
{
|
||||
$sValue->Rewind();
|
||||
$aItems = array();
|
||||
while ($oObj = $sValue->Fetch())
|
||||
{
|
||||
// Show only relevant information (hide the external key to the current object)
|
||||
$aAttributes = array();
|
||||
foreach(MetaModel::ListAttributeDefs($this->GetLinkedClass()) as $sAttCode => $oAttDef)
|
||||
{
|
||||
if ($sAttCode == $this->GetExtKeyToMe()) continue;
|
||||
if ($oAttDef->IsExternalField()) continue;
|
||||
if (!$oAttDef->IsDirectField()) continue;
|
||||
if (!$oAttDef->IsScalar()) continue;
|
||||
$sAttValue = $oObj->GetAsCSV($sAttCode, $sSepValue, '');
|
||||
if (strlen($sAttValue) > 0)
|
||||
{
|
||||
$sAttributeData = str_replace($sAttributeQualifier, $sAttributeQualifier.$sAttributeQualifier, $sAttCode.$sSepValue.$sAttValue);
|
||||
$aAttributes[] = $sAttributeQualifier.$sAttributeData.$sAttributeQualifier;
|
||||
}
|
||||
}
|
||||
$sAttributes = implode($sSepAttribute, $aAttributes);
|
||||
$aItems[] = $sAttributes;
|
||||
}
|
||||
$sRes = implode($sSepItem, $aItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sRes = '';
|
||||
}
|
||||
$sRes = str_replace($sTextQualifier, $sTextQualifier.$sTextQualifier, $sRes);
|
||||
$sRes = $sTextQualifier.$sRes.$sTextQualifier;
|
||||
return $sRes;
|
||||
}
|
||||
|
||||
public function DuplicatesAllowed() {return false;} // No duplicates for 1:n links, never
|
||||
|
||||
// Specific to this kind of attribute : transform a string into a value
|
||||
public function MakeValueFromString($sProposedValue, $sSepItem = null, $sSepAttribute = null, $sSepValue = null, $sAttributeQualifier = null)
|
||||
{
|
||||
if (is_null($sSepItem))
|
||||
{
|
||||
$sSepItem = MetaModel::GetConfig()->Get('link_set_item_separator');
|
||||
}
|
||||
if (is_null($sSepAttribute))
|
||||
{
|
||||
$sSepAttribute = MetaModel::GetConfig()->Get('link_set_attribute_separator');
|
||||
}
|
||||
if (is_null($sSepValue))
|
||||
{
|
||||
$sSepValue = MetaModel::GetConfig()->Get('link_set_value_separator');
|
||||
}
|
||||
if (is_null($sAttributeQualifier))
|
||||
{
|
||||
$sAttributeQualifier = MetaModel::GetConfig()->Get('link_set_attribute_qualifier');
|
||||
}
|
||||
|
||||
$sTargetClass = $this->Get('linked_class');
|
||||
|
||||
$sInput = str_replace($sSepItem, "\n", $sProposedValue);
|
||||
$oCSVParser = new CSVParser($sInput, $sSepAttribute, $sAttributeQualifier);
|
||||
|
||||
$aInput = $oCSVParser->ToArray(0 /* do not skip lines */);
|
||||
|
||||
$aLinks = array();
|
||||
foreach($aInput as $aRow)
|
||||
{
|
||||
$aNewRow = array();
|
||||
$oLink = MetaModel::NewObject($sTargetClass);
|
||||
$aExtKeys = array();
|
||||
foreach($aRow as $sCell)
|
||||
{
|
||||
$iSepPos = strpos($sCell, $sSepValue);
|
||||
if ($iSepPos === false)
|
||||
{
|
||||
// Houston...
|
||||
throw new CoreException('Wrong format for link attribute specification', array('value' => $sCell));
|
||||
}
|
||||
|
||||
$sAttCode = trim(substr($sCell, 0, $iSepPos));
|
||||
$sValue = substr($sCell, $iSepPos + strlen($sSepValue));
|
||||
|
||||
if (preg_match('/^(.+)->(.+)$/', $sAttCode, $aMatches))
|
||||
{
|
||||
$sKeyAttCode = $aMatches[1];
|
||||
$sRemoteAttCode = $aMatches[2];
|
||||
$aExtKeys[$sKeyAttCode][$sRemoteAttCode] = $sValue;
|
||||
if (!MetaModel::IsValidAttCode($sTargetClass, $sKeyAttCode))
|
||||
{
|
||||
throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sTargetClass, 'attcode' => $sKeyAttCode));
|
||||
}
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef($sTargetClass, $sKeyAttCode);
|
||||
$sRemoteClass = $oKeyAttDef->GetTargetClass();
|
||||
if (!MetaModel::IsValidAttCode($sRemoteClass, $sRemoteAttCode))
|
||||
{
|
||||
throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sRemoteClass, 'attcode' => $sRemoteAttCode));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(!MetaModel::IsValidAttCode($sTargetClass, $sAttCode))
|
||||
{
|
||||
throw new CoreException('Wrong attribute code for link attribute specification', array('class' => $sTargetClass, 'attcode' => $sAttCode));
|
||||
}
|
||||
$oLink->Set($sAttCode, $sValue);
|
||||
}
|
||||
}
|
||||
// Set external keys from search conditions
|
||||
foreach ($aExtKeys as $sKeyAttCode => $aReconciliation)
|
||||
{
|
||||
$oKeyAttDef = MetaModel::GetAttributeDef($sTargetClass, $sKeyAttCode);
|
||||
$sKeyClass = $oKeyAttDef->GetTargetClass();
|
||||
$oExtKeyFilter = new CMDBSearchFilter($sKeyClass);
|
||||
$aReconciliationDesc = array();
|
||||
foreach($aReconciliation as $sRemoteAttCode => $sValue)
|
||||
{
|
||||
$oExtKeyFilter->AddCondition($sRemoteAttCode, $sValue, '=');
|
||||
$aReconciliationDesc[] = "$sRemoteAttCode=$sValue";
|
||||
}
|
||||
$oExtKeySet = new CMDBObjectSet($oExtKeyFilter);
|
||||
switch($oExtKeySet->Count())
|
||||
{
|
||||
case 0:
|
||||
$sReconciliationDesc = implode(', ', $aReconciliationDesc);
|
||||
throw new CoreException("Found no match", array('ext_key' => $sKeyAttCode, 'reconciliation' => $sReconciliationDesc));
|
||||
break;
|
||||
case 1:
|
||||
$oRemoteObj = $oExtKeySet->Fetch();
|
||||
$oLink->Set($sKeyAttCode, $oRemoteObj->GetKey());
|
||||
break;
|
||||
default:
|
||||
$sReconciliationDesc = implode(', ', $aReconciliationDesc);
|
||||
throw new CoreException("Found several matches", array('ext_key' => $sKeyAttCode, 'reconciliation' => $sReconciliationDesc));
|
||||
// Found several matches, ambiguous
|
||||
}
|
||||
}
|
||||
|
||||
$aLinks[] = $oLink;
|
||||
}
|
||||
$oSet = DBObjectSet::FromArray($sTargetClass, $aLinks);
|
||||
return $oSet;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -821,12 +988,12 @@ class AttributeString extends AttributeDBField
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
$sFrom = array("\r\n", $sTextQualifier);
|
||||
$sTo = array("\n", $sTextQualifier.$sTextQualifier);
|
||||
$sEscaped = str_replace($sFrom, $sTo, (string)$sValue);
|
||||
return '"'.$sEscaped.'"';
|
||||
return $sTextQualifier.$sEscaped.$sTextQualifier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -864,7 +1031,7 @@ class AttributeClass extends AttributeString
|
||||
return $sDefault;
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
if (empty($sValue)) return '';
|
||||
return MetaModel::GetName($sValue);
|
||||
@@ -953,7 +1120,7 @@ class AttributeFinalClass extends AttributeString
|
||||
return $this->m_sValue;
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
if (empty($sValue)) return '';
|
||||
return MetaModel::GetName($sValue);
|
||||
@@ -995,7 +1162,7 @@ class AttributePassword extends AttributeString
|
||||
return array();
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
if (strlen($sValue) == 0)
|
||||
{
|
||||
@@ -1091,7 +1258,7 @@ class AttributeText extends AttributeString
|
||||
return 65535;
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
$sValue = parent::GetAsHTML($sValue);
|
||||
|
||||
@@ -1167,7 +1334,7 @@ class AttributeText extends AttributeString
|
||||
return $sValue;
|
||||
}
|
||||
|
||||
public function GetAsXML($value)
|
||||
public function GetAsXML($value, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2xml($value);
|
||||
}
|
||||
@@ -1199,7 +1366,7 @@ class AttributeHTML extends AttributeText
|
||||
{
|
||||
public function GetEditClass() {return "HTML";}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
return $sValue;
|
||||
}
|
||||
@@ -1218,7 +1385,7 @@ class AttributeEmailAddress extends AttributeString
|
||||
return "^[a-zA-Z0-9._-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,4}$";
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
if (empty($sValue)) return '';
|
||||
return '<a class="mailto" href="mailto:'.$sValue.'">'.parent::GetAsHTML($sValue).'</a>';
|
||||
@@ -1275,7 +1442,7 @@ class AttributeTemplateHTML extends AttributeText
|
||||
{
|
||||
public function GetEditClass() {return "HTML";}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
return $sValue;
|
||||
}
|
||||
@@ -1289,7 +1456,7 @@ class AttributeTemplateHTML extends AttributeText
|
||||
*/
|
||||
class AttributeWikiText extends AttributeText
|
||||
{
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
// [SELECT xxxx.... [label]] => hyperlink to a result list
|
||||
// {SELECT xxxx.... [label]} => result list displayed inline
|
||||
@@ -1374,7 +1541,7 @@ class AttributeEnum extends AttributeString
|
||||
return parent::GetBasicFilterSQLExpr($sOpCode, $value);
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
if (is_null($sValue))
|
||||
{
|
||||
@@ -1581,17 +1748,17 @@ class AttributeDateTime extends AttributeDBField
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2html($value);
|
||||
}
|
||||
|
||||
public function GetAsXML($value)
|
||||
public function GetAsXML($value, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2xml($value);
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
$sFrom = array("\r\n", $sTextQualifier);
|
||||
$sTo = array("\n", $sTextQualifier.$sTextQualifier);
|
||||
@@ -1702,7 +1869,7 @@ class AttributeDuration extends AttributeInteger
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2html(self::FormatDuration($value));
|
||||
}
|
||||
@@ -1788,7 +1955,7 @@ AttributeDate::InitStatics();
|
||||
*/
|
||||
class AttributeDeadline extends AttributeDateTime
|
||||
{
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
$sResult = '';
|
||||
if ($value !== null)
|
||||
@@ -2144,17 +2311,17 @@ class AttributeExternalField extends AttributeDefinition
|
||||
return $oExtAttDef->FromSQLToValue($aCols, $sPrefix);
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
return $oExtAttDef->GetAsHTML($value);
|
||||
}
|
||||
public function GetAsXML($value)
|
||||
public function GetAsXML($value, $oHostObject = null)
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
return $oExtAttDef->GetAsXML($value);
|
||||
}
|
||||
public function GetAsCSV($value, $sSeparator = ',', $sTestQualifier = '"')
|
||||
public function GetAsCSV($value, $sSeparator = ',', $sTestQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
$oExtAttDef = $this->GetExtAttDef();
|
||||
return $oExtAttDef->GetAsCSV($value, $sSeparator, $sTestQualifier);
|
||||
@@ -2176,7 +2343,7 @@ class AttributeURL extends AttributeString
|
||||
|
||||
public function GetEditClass() {return "String";}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
$sTarget = $this->Get("target");
|
||||
if (empty($sTarget)) $sTarget = "_blank";
|
||||
@@ -2326,7 +2493,7 @@ class AttributeBlob extends AttributeDefinition
|
||||
return 'true';
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
if (is_object($value))
|
||||
{
|
||||
@@ -2334,12 +2501,12 @@ class AttributeBlob extends AttributeDefinition
|
||||
}
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
return ''; // Not exportable in CSV !
|
||||
}
|
||||
|
||||
public function GetAsXML($value)
|
||||
public function GetAsXML($value, $oHostObject = null)
|
||||
{
|
||||
return ''; // Not exportable in XML, or as CDATA + some subtags ??
|
||||
}
|
||||
@@ -2479,7 +2646,7 @@ class AttributeOneWayPassword extends AttributeDefinition
|
||||
return 'true';
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
if (is_object($value))
|
||||
{
|
||||
@@ -2487,12 +2654,12 @@ class AttributeOneWayPassword extends AttributeDefinition
|
||||
}
|
||||
}
|
||||
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"')
|
||||
public function GetAsCSV($sValue, $sSeparator = ',', $sTextQualifier = '"', $oHostObject = null)
|
||||
{
|
||||
return ''; // Not exportable in CSV
|
||||
}
|
||||
|
||||
public function GetAsXML($value)
|
||||
public function GetAsXML($value, $oHostObject = null)
|
||||
{
|
||||
return ''; // Not exportable in XML
|
||||
}
|
||||
@@ -2544,7 +2711,7 @@ class AttributeTable extends AttributeText
|
||||
return $aValues;
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
if (!is_array($value))
|
||||
{
|
||||
@@ -2589,7 +2756,7 @@ class AttributePropertySet extends AttributeTable
|
||||
return $proposedValue;
|
||||
}
|
||||
|
||||
public function GetAsHTML($value)
|
||||
public function GetAsHTML($value, $oHostObject = null)
|
||||
{
|
||||
if (!is_array($value))
|
||||
{
|
||||
@@ -2737,6 +2904,11 @@ class AttributeFriendlyName extends AttributeComputedFieldVoid
|
||||
return false;
|
||||
}
|
||||
|
||||
public function IsDirectField()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public function SetFixedValue($sValue)
|
||||
{
|
||||
$this->m_sValue = $sValue;
|
||||
@@ -2746,7 +2918,7 @@ class AttributeFriendlyName extends AttributeComputedFieldVoid
|
||||
return $this->m_sValue;
|
||||
}
|
||||
|
||||
public function GetAsHTML($sValue)
|
||||
public function GetAsHTML($sValue, $oHostObject = null)
|
||||
{
|
||||
return Str::pure2html((string)$sValue);
|
||||
}
|
||||
|
||||
@@ -52,19 +52,13 @@ abstract class CellChangeSpec
|
||||
$this->m_sOql = $sOql;
|
||||
}
|
||||
|
||||
static protected function ValueAsHtml($value)
|
||||
public function GetPureValue()
|
||||
{
|
||||
if (MetaModel::IsValidObject($value))
|
||||
{
|
||||
return $value->GetHyperLink();
|
||||
}
|
||||
else
|
||||
{
|
||||
return htmlentities($value, ENT_QUOTES, 'UTF-8');
|
||||
}
|
||||
// Todo - distinguish both values
|
||||
return $this->m_proposedValue;
|
||||
}
|
||||
|
||||
public function GetValue()
|
||||
public function GetDisplayableValue()
|
||||
{
|
||||
return $this->m_proposedValue;
|
||||
}
|
||||
@@ -101,10 +95,10 @@ class CellStatus_Modify extends CellChangeSpec
|
||||
return 'Modified';
|
||||
}
|
||||
|
||||
public function GetPreviousValue()
|
||||
{
|
||||
return $this->m_previousValue;
|
||||
}
|
||||
//public function GetPreviousValue()
|
||||
//{
|
||||
// return $this->m_previousValue;
|
||||
//}
|
||||
}
|
||||
|
||||
class CellStatus_Issue extends CellStatus_Modify
|
||||
@@ -270,6 +264,22 @@ class BulkChange
|
||||
$this->m_aOnDisappear = $aOnDisappear;
|
||||
}
|
||||
|
||||
protected $m_bReportHtml = false;
|
||||
protected $m_sReportCsvSep = ',';
|
||||
protected $m_sReportCsvDelimiter = '"';
|
||||
|
||||
public function SetReportHtml()
|
||||
{
|
||||
$this->m_bReportHtml = true;
|
||||
}
|
||||
|
||||
public function SetReportCsv($sSeparator = ',', $sDelimiter = '"')
|
||||
{
|
||||
$this->m_bReportHtml = false;
|
||||
$this->m_sReportCsvSep = $sSeparator;
|
||||
$this->m_sReportCsvDelimiter = $sDelimiter;
|
||||
}
|
||||
|
||||
protected function ResolveExternalKey($aRowData, $sAttCode, &$aResults)
|
||||
{
|
||||
$oExtKey = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
@@ -388,15 +398,31 @@ class BulkChange
|
||||
// skip the private key, if any
|
||||
if ($sAttCode == 'id') continue;
|
||||
|
||||
$res = $oTargetObj->CheckValue($sAttCode, $aRowData[$iCol]);
|
||||
if ($res === true)
|
||||
$oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode);
|
||||
if ($oAttDef->IsLinkSet())
|
||||
{
|
||||
$oTargetObj->Set($sAttCode, $aRowData[$iCol]);
|
||||
try
|
||||
{
|
||||
$oSet = $oAttDef->MakeValueFromString($aRowData[$iCol]);
|
||||
$oTargetObj->Set($sAttCode, $oSet);
|
||||
}
|
||||
catch(CoreException $e)
|
||||
{
|
||||
$aErrors[$sAttCode] = "Failed to process input: ".$e->getMessage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// $res is a string with the error description
|
||||
$aErrors[$sAttCode] = "Unexpected value for attribute '$sAttCode': $res";
|
||||
{
|
||||
$res = $oTargetObj->CheckValue($sAttCode, $aRowData[$iCol]);
|
||||
if ($res === true)
|
||||
{
|
||||
$oTargetObj->Set($sAttCode, $aRowData[$iCol]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// $res is a string with the error description
|
||||
$aErrors[$sAttCode] = "Unexpected value for attribute '$sAttCode': $res";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -409,19 +435,29 @@ class BulkChange
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Void($aRowData[$iCol]);
|
||||
}
|
||||
if ($this->m_bReportHtml)
|
||||
{
|
||||
$sCurValue = $oTargetObj->GetAsHTML($sAttCode);
|
||||
$sOrigValue = $oTargetObj->GetOriginalAsHTML($sAttCode);
|
||||
}
|
||||
else
|
||||
{
|
||||
$sCurValue = $oTargetObj->GetAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter);
|
||||
$sOrigValue = $oTargetObj->GetOriginalAsCSV($sAttCode, $this->m_sReportCsvSep, $this->m_sReportCsvDelimiter);
|
||||
}
|
||||
if (isset($aErrors[$sAttCode]))
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Issue($oTargetObj->Get($sAttCode), $oTargetObj->GetOriginal($sAttCode), $aErrors[$sAttCode]);
|
||||
$aResults[$iCol]= new CellStatus_Issue($sCurValue, $sOrigValue, $aErrors[$sAttCode]);
|
||||
}
|
||||
elseif (array_key_exists($sAttCode, $aChangedFields))
|
||||
{
|
||||
if ($oTargetObj->IsNew())
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Void($oTargetObj->Get($sAttCode));
|
||||
$aResults[$iCol]= new CellStatus_Void($sCurValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
$aResults[$iCol]= new CellStatus_Modify($oTargetObj->Get($sAttCode), $oTargetObj->GetOriginal($sAttCode));
|
||||
$aResults[$iCol]= new CellStatus_Modify($sCurValue, $sOrigValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -970,7 +1006,7 @@ EOF
|
||||
{
|
||||
$aObjects[$iObjId]['__created__'] = true;
|
||||
}
|
||||
elseif (is_subclass_of($oOperation, 'CMDBChangeOpSetAttribute'))
|
||||
elseif ($oOperation instanceof CMDBChangeOpSetAttribute)
|
||||
{
|
||||
$sAttCode = $oOperation->Get('attcode');
|
||||
|
||||
|
||||
@@ -221,6 +221,38 @@ class Config
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'link_set_item_separator' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Link set from string: line separator',
|
||||
'default' => '|',
|
||||
'value' => '|',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'link_set_attribute_separator' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Link set from string: attribute separator',
|
||||
'default' => ';',
|
||||
'value' => ';',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'link_set_value_separator' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Link set from string: value separator (between the attcode and the value itself',
|
||||
'default' => ':',
|
||||
'value' => ':',
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
'link_set_attribute_qualifier' => array(
|
||||
'type' => 'string',
|
||||
'description' => 'Link set from string: attribute qualifier (encloses both the attcode and the value)',
|
||||
'default' => "'",
|
||||
'value' => "'",
|
||||
'source_of_value' => '',
|
||||
'show_in_conf_sample' => true,
|
||||
),
|
||||
);
|
||||
|
||||
public function IsProperty($sPropCode)
|
||||
|
||||
@@ -184,6 +184,7 @@ class CSVParser
|
||||
{
|
||||
if ($i == $iDataLength)
|
||||
{
|
||||
$c = null;
|
||||
$iEvent = evEND;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -481,13 +481,31 @@ abstract class DBObject
|
||||
public function GetAsXML($sAttCode)
|
||||
{
|
||||
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAtt->GetAsXML($this->Get($sAttCode));
|
||||
return $oAtt->GetAsXML($this->Get($sAttCode), $this);
|
||||
}
|
||||
|
||||
public function GetAsCSV($sAttCode, $sSeparator = ',', $sTextQualifier = '"')
|
||||
{
|
||||
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAtt->GetAsCSV($this->Get($sAttCode), $sSeparator, $sTextQualifier);
|
||||
return $oAtt->GetAsCSV($this->Get($sAttCode), $sSeparator, $sTextQualifier, $this);
|
||||
}
|
||||
|
||||
public function GetOriginalAsHTML($sAttCode)
|
||||
{
|
||||
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAtt->GetAsHTML($this->GetOriginal($sAttCode), $this);
|
||||
}
|
||||
|
||||
public function GetOriginalAsXML($sAttCode)
|
||||
{
|
||||
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAtt->GetAsXML($this->GetOriginal($sAttCode), $this);
|
||||
}
|
||||
|
||||
public function GetOriginalAsCSV($sAttCode, $sSeparator = ',', $sTextQualifier = '"')
|
||||
{
|
||||
$oAtt = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
|
||||
return $oAtt->GetAsCSV($this->GetOriginal($sAttCode), $sSeparator, $sTextQualifier, $this);
|
||||
}
|
||||
|
||||
protected static function MakeHyperLink($sObjClass, $sObjKey, $sLabel = '')
|
||||
|
||||
@@ -163,8 +163,9 @@ function GetMappingForField($sClassName, $sFieldName, $iFieldIndex, $bAdvancedMo
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ( ($oAttDef->IsWritable()) && (!$oAttDef->IsLinkSet()) )
|
||||
else if ($oAttDef->IsWritable() && ($bAdvancedMode || !$oAttDef->IsLinkset()))
|
||||
{
|
||||
|
||||
if (!$oAttDef->IsNullAllowed())
|
||||
{
|
||||
$sStar = '*';
|
||||
|
||||
@@ -315,7 +315,8 @@ try
|
||||
empty($sSynchroScope) ? null : $sSynchroScope,
|
||||
$aSynchroUpdate
|
||||
);
|
||||
|
||||
$oBulk->SetReportHtml();
|
||||
|
||||
$oPage->add('<input type="hidden" name="csvdata_truncated" id="csvdata_truncated" value="'.htmlentities($sCSVDataTruncated, ENT_QUOTES, 'UTF-8').'"/>');
|
||||
$aRes = $oBulk->Process($oMyChange);
|
||||
|
||||
@@ -350,7 +351,7 @@ try
|
||||
case 'RowStatus_NoChange':
|
||||
$iUnchanged++;
|
||||
$sFinalClass = $aResRow['finalclass'];
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetValue());
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
|
||||
$sUrl = $oObj->GetHyperlink();
|
||||
$sStatus = '<img src="../images/unchanged.png" title="Unchanged">';
|
||||
$sCSSRowClass = 'row_unchanged';
|
||||
@@ -359,7 +360,7 @@ try
|
||||
case 'RowStatus_Modify':
|
||||
$iModified++;
|
||||
$sFinalClass = $aResRow['finalclass'];
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetValue());
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
|
||||
$sUrl = $oObj->GetHyperlink();
|
||||
$sStatus = '<img src="../images/modified.png" title="Modified">';
|
||||
$sCSSRowClass = 'row_modified';
|
||||
@@ -368,7 +369,7 @@ try
|
||||
case 'RowStatus_Disappeared':
|
||||
$iModified++;
|
||||
$sFinalClass = $aResRow['finalclass'];
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetValue());
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
|
||||
$sUrl = $oObj->GetHyperlink();
|
||||
$sStatus = '<img src="../images/delete.png" title="Missing">';
|
||||
$sCSSRowClass = 'row_modified';
|
||||
@@ -394,7 +395,7 @@ try
|
||||
else
|
||||
{
|
||||
$sFinalClass = $aResRow['finalclass'];
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetValue());
|
||||
$oObj = MetaModel::GetObject($sFinalClass, $aResRow['id']->GetPureValue());
|
||||
$sUrl = $oObj->GetHyperlink();
|
||||
$sMessage = 'Object created';
|
||||
}
|
||||
@@ -443,7 +444,7 @@ try
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
$sHtmlValue = htmlentities($oCellStatus->GetValue(), ENT_QUOTES, 'UTF-8');
|
||||
$sHtmlValue = $oCellStatus->GetDisplayableValue();
|
||||
switch(get_class($oCellStatus))
|
||||
{
|
||||
case 'CellStatus_Issue':
|
||||
|
||||
@@ -1326,26 +1326,45 @@ class TestItopBulkLoad extends TestBizModel
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
$oParser = new CSVParser("name,org_id->name,brand,model
|
||||
Server1,Demo,,
|
||||
server4,Demo,,
|
||||
$sLogin = 'testbulkload_'.time();
|
||||
|
||||
$oParser = new CSVParser("login,contactid->name,password,profile_list
|
||||
_1_$sLogin,Picasso,secret1,profileid:10;reason:service manager|profileid->name:Problem Manager;'reason:toto;problem manager'
|
||||
_2_$sLogin,Picasso,secret2,
|
||||
", ',', '"');
|
||||
$aData = $oParser->ToArray(1, array('_name', '_org_name', '_brand', '_model'));
|
||||
$aData = $oParser->ToArray(1, array('_login', '_contact_name', '_password', '_profiles'));
|
||||
self::DumpVariable($aData);
|
||||
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', 'patator');
|
||||
$oUser->Set('password', 'patator');
|
||||
//$oUser->Set('contactid', 0);
|
||||
//$oUser->Set('language', $sLanguage);
|
||||
|
||||
$aProfiles = array(
|
||||
array(
|
||||
'profileid' => 10, // Service Manager
|
||||
'reason' => 'service manager',
|
||||
),
|
||||
array(
|
||||
'profileid->name' => 'Problem Manager',
|
||||
'reason' => 'problem manager',
|
||||
),
|
||||
);
|
||||
|
||||
$oBulk = new BulkChange(
|
||||
'Server',
|
||||
'UserLocal',
|
||||
$aData,
|
||||
// attributes
|
||||
array('name' => '_name', 'brand' => '_brand', 'model' => '_model'),
|
||||
array('login' => '_login', 'password' => '_password', 'profile_list' => '_profiles'),
|
||||
// ext keys
|
||||
array('org_id' => array('name' => '_org_name')),
|
||||
array('contactid' => array('name' => '_contact_name')),
|
||||
// reconciliation
|
||||
array('name'),
|
||||
array('login'),
|
||||
// Synchro - scope
|
||||
"SELECT Server",
|
||||
"SELECT UserLocal",
|
||||
// Synchro - set attribute on missing objects
|
||||
array ('brand' => 'you let package', 'model' => 'tpe', 'cpu' => 'it is pay you')
|
||||
array ('password' => 'terminated', 'login' => 'terminated'.time())
|
||||
);
|
||||
|
||||
if (false)
|
||||
@@ -1786,6 +1805,19 @@ class TestImportREST extends TestWebServices
|
||||
),
|
||||
'csvdata' => "org_name;name;address\nDemo;Le pantheon;restore address?",
|
||||
),
|
||||
array(
|
||||
'desc' => 'Load a user account',
|
||||
'login' => 'admin',
|
||||
'password' => 'admin',
|
||||
'args' => array(
|
||||
'class' => 'UserLocal',
|
||||
'output' => 'details',
|
||||
'separator' => ',',
|
||||
'simulate' => '0',
|
||||
'comment' => 'automated testing'
|
||||
),
|
||||
'csvdata' => "login,password,profile_list\nby_import_csv,fakepwd,profileid->name:Configuration Manager|profileid:10;reason:direct id",
|
||||
),
|
||||
);
|
||||
|
||||
$sSubTests = utils::ReadParam('subtests', null);
|
||||
@@ -3105,5 +3137,38 @@ class TestCreateObjects extends TestBizModel
|
||||
}
|
||||
}
|
||||
|
||||
class TestSetLinkset extends TestBizModel
|
||||
{
|
||||
static public function GetName()
|
||||
{
|
||||
return 'Itop - Link set from a string';
|
||||
}
|
||||
|
||||
static public function GetDescription()
|
||||
{
|
||||
return 'Create a user account, setting its profile by the mean of a string (prerequisite to CSV import of linksets)';
|
||||
}
|
||||
|
||||
static public function GetConfigFile() {return '/config-itop.php';}
|
||||
|
||||
protected function DoExecute()
|
||||
{
|
||||
$oUser = new UserLocal();
|
||||
$oUser->Set('login', 'patator'.time());
|
||||
$oUser->Set('password', 'patator');
|
||||
//$oUser->Set('contactid', 0);
|
||||
//$oUser->Set('language', $sLanguage);
|
||||
|
||||
$sLinkSetSpec = "profileid:10;reason:service manager|profileid->name:Problem Manager;'reason:problem manager;glandeur";
|
||||
|
||||
$oAttDef = MetaModel::GetAttributeDef('UserLocal', 'profile_list');
|
||||
$oSet = $oAttDef->MakeValueFromString($sLinkSetSpec);
|
||||
$oUser->Set('profile_list', $oSet);
|
||||
|
||||
// Create a change to record the history of the User object
|
||||
$this->ObjectToDB($oUser, $bReload = true);
|
||||
echo "<p>Created: {$oUser->GetHyperLink()}</p>";
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
|
||||
@@ -42,6 +42,8 @@ $currentOrganization = utils::ReadParam('org_id', '');
|
||||
// Main program
|
||||
$sExpression = utils::ReadParam('expression', '');
|
||||
$sFormat = strtolower(utils::ReadParam('format', 'html'));
|
||||
$sFields = utils::ReadParam('fields', ''); // CSV field list
|
||||
|
||||
$oP = null;
|
||||
|
||||
if (!empty($sExpression))
|
||||
@@ -77,7 +79,7 @@ if (!empty($sExpression))
|
||||
|
||||
case 'csv':
|
||||
$oP = new CSVPage("iTop - Export");
|
||||
cmdbAbstractObject::DisplaySetAsCSV($oP, $oSet);
|
||||
cmdbAbstractObject::DisplaySetAsCSV($oP, $oSet, array('fields' => $sFields));
|
||||
break;
|
||||
|
||||
case 'xml':
|
||||
|
||||
@@ -384,7 +384,7 @@ try
|
||||
// Ignore any trailing "star" (*) that simply indicates a mandatory field
|
||||
$sFieldName = $aMatches[1];
|
||||
}
|
||||
if (preg_match('/^(.*)->(.*)$/', trim($sFieldName), $aMatches))
|
||||
if (preg_match('/^(.+)->(.+)$/', trim($sFieldName), $aMatches))
|
||||
{
|
||||
// The column has been specified as "extkey->attcode"
|
||||
//
|
||||
@@ -472,7 +472,7 @@ try
|
||||
throw new BulkLoadException("Reconciliation keys not found in the input columns '$sReconcKey' (class: '$sClass')");
|
||||
}
|
||||
|
||||
if (preg_match('/^(.*)->(.*)$/', trim($sReconcKey), $aMatches))
|
||||
if (preg_match('/^(.+)->(.+)$/', trim($sReconcKey), $aMatches))
|
||||
{
|
||||
// The column has been specified as "extkey->attcode"
|
||||
//
|
||||
@@ -697,7 +697,7 @@ try
|
||||
if (isset($aRowData["finalclass"]) && isset($aRowData["id"]))
|
||||
{
|
||||
$aRowDisp["__OBJECT_CLASS__"] = $aRowData["finalclass"];
|
||||
$aRowDisp["__OBJECT_ID__"] = $aRowData["id"]->GetValue();
|
||||
$aRowDisp["__OBJECT_ID__"] = $aRowData["id"]->GetDisplayableValue();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -714,7 +714,7 @@ try
|
||||
|
||||
if (is_object($value))
|
||||
{
|
||||
$aRowDisp["$sKey"] = $value->GetValue().$value->GetDescription();
|
||||
$aRowDisp["$sKey"] = $value->GetDisplayableValue().$value->GetDescription();
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user