diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 8e3d06ded..078de5cad 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -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\n"); diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 8c873117c..fcd71ec91 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -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('
', $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 ''.parent::GetAsHTML($sValue).''; @@ -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); } diff --git a/core/bulkchange.class.inc.php b/core/bulkchange.class.inc.php index 4f2a2cda7..bbd9678c0 100644 --- a/core/bulkchange.class.inc.php +++ b/core/bulkchange.class.inc.php @@ -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'); diff --git a/core/config.class.inc.php b/core/config.class.inc.php index af47849b8..a4a810435 100644 --- a/core/config.class.inc.php +++ b/core/config.class.inc.php @@ -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) diff --git a/core/csvparser.class.inc.php b/core/csvparser.class.inc.php index ec2e4955e..82947d6d8 100644 --- a/core/csvparser.class.inc.php +++ b/core/csvparser.class.inc.php @@ -184,6 +184,7 @@ class CSVParser { if ($i == $iDataLength) { + $c = null; $iEvent = evEND; } else diff --git a/core/dbobject.class.php b/core/dbobject.class.php index 138a29b94..62d86289d 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -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 = '') diff --git a/pages/ajax.csvimport.php b/pages/ajax.csvimport.php index 090c808a9..5837f57fd 100644 --- a/pages/ajax.csvimport.php +++ b/pages/ajax.csvimport.php @@ -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 = '*'; diff --git a/pages/csvimport.php b/pages/csvimport.php index adb436391..0e1eed462 100644 --- a/pages/csvimport.php +++ b/pages/csvimport.php @@ -315,7 +315,8 @@ try empty($sSynchroScope) ? null : $sSynchroScope, $aSynchroUpdate ); - + $oBulk->SetReportHtml(); + $oPage->add(''); $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 = ''; $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 = ''; $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 = ''; $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': diff --git a/test/testlist.inc.php b/test/testlist.inc.php index 1786d09ea..fb23b84bf 100644 --- a/test/testlist.inc.php +++ b/test/testlist.inc.php @@ -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 "

Created: {$oUser->GetHyperLink()}

"; + } +} ?> diff --git a/webservices/export.php b/webservices/export.php index 60c20f764..0c572197e 100644 --- a/webservices/export.php +++ b/webservices/export.php @@ -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': diff --git a/webservices/import.php b/webservices/import.php index c6949da36..cc298b53f 100644 --- a/webservices/import.php +++ b/webservices/import.php @@ -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 {