From 2e442dbaa0ecfc6efd741420d0c32d0a61e583c3 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Wed, 15 May 2013 15:56:42 +0000 Subject: [PATCH] #704: preserve the content of a "linkedset" when changing the initial state of the object being created ! SVN:trunk[2737] --- application/cmdbabstract.class.inc.php | 17 +++++++-- application/ui.linkswidget.class.inc.php | 30 +++++++++++----- core/attributedef.class.inc.php | 2 +- js/linkswidget.js | 45 ++++++++++++++++++++++-- js/wizardhelper.js | 45 ++++++++++++------------ 5 files changed, 103 insertions(+), 36 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index 8913fd345..bbb0f2472 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -80,6 +80,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay { protected $m_iFormId; // The ID of the form used to edit the object (when in edition mode !) static $iGlobalFormId = 1; + protected $aFieldsMap; /** * returns what will be the next ID for the forms @@ -289,6 +290,16 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay return $aFieldsMap; } + + /** + * Add a field to the map: attcode => id used when building a form + * @param string $sAttCode The attribute code of the field being edited + * @param string $sInputId The unique ID of the control/widget in the page + */ + protected function AddToFieldsMap($sAttCode, $sInputId) + { + $this->aFieldsMap[$sAttCode] = $sInputId; + } function DisplayBareRelations(WebPage $oPage, $bEditMode = false) { @@ -345,7 +356,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay $sDisplayValue = ''; // not used $aArgs = array('this' => $this); $sHTMLValue = "".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $oValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).''; - $aFieldsMap[$sAttCode] = $sInputId; + $this->AddToFieldsMap($sAttCode, $sInputId); $oPage->add($sHTMLValue); } else @@ -1819,6 +1830,7 @@ abstract class cmdbAbstractObject extends CMDBObject implements iDisplay public function DisplayModifyForm(WebPage $oPage, $aExtraParams = array()) { self::$iGlobalFormId++; + $this->aFieldsMap = array(); $sPrefix = ''; if (isset($aExtraParams['formPrefix'])) { @@ -1963,7 +1975,8 @@ EOF // Now display the relations, one tab per relation if (!isset($aExtraParams['noRelations'])) { - $this->DisplayBareRelations($oPage, true); // Edit mode + $this->DisplayBareRelations($oPage, true); // Edit mode, will fill $this->aFieldsMap + $aFieldsMap = array_merge($aFieldsMap, $this->aFieldsMap); } $oPage->SetCurrentTab(''); diff --git a/application/ui.linkswidget.class.inc.php b/application/ui.linkswidget.class.inc.php index bd906847e..4a63a39a6 100644 --- a/application/ui.linkswidget.class.inc.php +++ b/application/ui.linkswidget.class.inc.php @@ -106,7 +106,7 @@ class UILinksWidget $sPrefix = "$this->m_sAttCode{$this->m_sNameSuffix}"; $aRow = array(); $aFieldsMap = array(); - if(is_object($linkObjOrId)) + if(is_object($linkObjOrId) && (!$linkObjOrId->IsNew())) { $key = $linkObjOrId->GetKey(); $iRemoteObjKey = $linkObjOrId->Get($this->m_sExtKeyToRemote); @@ -130,12 +130,24 @@ class UILinksWidget else { // form for creating a new record + if (is_object($linkObjOrId)) + { + // New link existing only in memory + $oNewLinkObj = $linkObjOrId; + $iRemoteObjKey = $oNewLinkObj->Get($this->m_sExtKeyToRemote); + $oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, $iRemoteObjKey); + $oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields + $linkObjOrId = -$iRemoteObjKey; + } + else + { + $iRemoteObjKey = -$linkObjOrId; + $oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass); + $oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, -$linkObjOrId); + $oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields + $oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields + } $sPrefix .= "[$linkObjOrId]["; - $iRemoteObjKey = -$linkObjOrId; - $oNewLinkObj = MetaModel::NewObject($this->m_sLinkedClass); - $oRemoteObj = MetaModel::GetObject($this->m_sRemoteClass, -$linkObjOrId); - $oNewLinkObj->Set($this->m_sExtKeyToRemote, $oRemoteObj); // Setting the extkey with the object alsoo fills the related external fields - $oNewLinkObj->Set($this->m_sExtKeyToMe, $oCurrentObj); // Setting the extkey with the object also fills the related external fields $sNameSuffix = "]"; // To make a tabular form $aArgs['prefix'] = $sPrefix; $aArgs['wizHelper'] = "oWizardHelper{$this->m_iInputId}_".(-$linkObjOrId); @@ -275,6 +287,7 @@ EOF $sHtmlValue = ''; $sTargetClass = self::GetTargetClass($this->m_sClass, $this->m_sAttCode); $sHtmlValue .= "
m_sAttCode}{$this->m_sNameSuffix}\">\n"; + $sHtmlValue .= "m_iInputId}\">\n"; $oValue->Rewind(); $aForm = array(); while($oCurrentLink = $oValue->Fetch()) @@ -284,7 +297,7 @@ EOF if ($oCurrentLink->IsNew()) { $key = -$oLinkedObj->GetKey(); - $aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $key, $aArgs, $oCurrentObj); + $aForm[$key] = $this->GetFormRow($oPage, $oLinkedObj, $oCurrentLink, $aArgs, $oCurrentObj); } else { @@ -297,8 +310,9 @@ EOF $sDuplicates = ($this->m_bDuplicatesAllowed) ? 'true' : 'false'; $sWizHelper = 'oWizardHelper'.$sFormPrefix; $oPage->add_ready_script(<<m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper); + oWidget{$this->m_iInputId} = new LinksWidget('{$this->m_sAttCode}{$this->m_sNameSuffix}', '{$this->m_sClass}', '{$this->m_sAttCode}', '{$this->m_iInputId}', '{$this->m_sNameSuffix}', $sDuplicates, $sWizHelper, '{$this->m_sExtKeyToRemote}'); oWidget{$this->m_iInputId}.Init(); + $('#{$this->m_iInputId}').bind('update_value', function() { $(this).val(oWidget{$this->m_iInputId}.GetUpdatedValue()); }) EOF ); $sHtmlValue .= "     m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >"; diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 01c62f1f5..55a2b3682 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -4464,7 +4464,7 @@ class AttributeComputedFieldVoid extends AttributeDefinition public function GetEditClass() {return "";} public function GetValuesDef() {return null;} - public function GetPrerequisiteAttributes() {return $this->Get("depends_on");} + public function GetPrerequisiteAttributes() {return $this->GetOptional("depends_on", array());} public function IsDirectField() {return true;} public function IsScalar() {return true;} diff --git a/js/linkswidget.js b/js/linkswidget.js index 69763462e..1b8d61f00 100644 --- a/js/linkswidget.js +++ b/js/linkswidget.js @@ -1,5 +1,5 @@ // JavaScript Document -function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizHelper) +function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizHelper, sExtKeyToRemote) { this.id = id; this.iInputId = iInputId; @@ -8,6 +8,7 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH this.sSuffix = sSuffix; this.bDuplicates = bDuplicates; this.oWizardHelper = oWizHelper; + this.sExtKeyToRemote = sExtKeyToRemote; var me = this; this.Init = function() { @@ -59,7 +60,7 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH { $('#'+me.id+'_btnRemove').attr('disabled','disabled'); } - } + }; this.AddObjects = function() { @@ -288,4 +289,44 @@ function LinksWidget(id, sClass, sAttCode, iInputId, sSuffix, bDuplicates, oWizH form_height = searchForm.outerHeight(); results.height(height - form_height - 40); // Leave some space for the buttons }; + + this.GetUpdatedValue = function() + { + var sSelector = '#linkedset_'+me.id+' input[name^=attr_'+me.id+']'; + var aIndexes = []; + var aValues = []; + $(sSelector).each(function() { + var re = /\[([^\[]+)\]\[(.+)\]/; + var aMatches = []; + if (aMatches = this.name.match(re)) + { + var idx = aMatches[1]; + var index = aIndexes.indexOf(idx); + if (index == -1) + { + aIndexes.push(idx); + index = aIndexes.indexOf(idx); + aValues[index] = {}; + } + var value = $(this).val(); + if (aMatches[2] == "id") + { + var iId = parseInt(aMatches[1], 10); + if (iId < 0) + { + aValues[index][me.sExtKeyToRemote] = -iId; + } + else + { + aValues[index]['id'] = value; + } + } + else + { + aValues[index][aMatches[2]] = value; + } + } + }); + return JSON.stringify(aValues); + }; } diff --git a/js/wizardhelper.js b/js/wizardhelper.js index 26efa921d..8dae04f13 100644 --- a/js/wizardhelper.js +++ b/js/wizardhelper.js @@ -36,19 +36,18 @@ function WizardHelper(sClass, sFormPrefix, sState) this.SetFieldsMap = function (oFieldsMap) { this.m_oData.m_oFieldsMap = oFieldsMap; - } + }; this.SetFieldsCount = function (count) { this.m_oData.m_iFieldsCount = count; - - } + }; this.GetFieldId = function(sFieldName) { id = this.m_oData.m_oFieldsMap[sFieldName]; return id; - } + }; this.RequestDefaultValue = function (sFieldName) { @@ -57,26 +56,28 @@ function WizardHelper(sClass, sFormPrefix, sState) { this.m_oData.m_aDefaultValueRequested.push(sFieldName); } - } + }; + this.RequestAllowedValues = function (sFieldName) { this.m_oData.m_aAllowedValuesRequested.push(sFieldName); - } + }; + this.SetCurrentValue = function (sFieldName, currentValue) { this.m_oData.m_oCurrentValues[sFieldName] = currentValue; - } + }; this.ToJSON = function () { return JSON.stringify(this.m_oData); - } + }; this.FromJSON = function (sJSON) { //console.log('Parsing JSON:'+sJSON); this.m_oData = JSON.parse(sJSON); - } + }; this.ResetQuery = function () { @@ -84,7 +85,7 @@ function WizardHelper(sClass, sFormPrefix, sState) this.m_oData.m_oDefaultValue = {}; this.m_oData.m_aAllowedValuesRequested = []; this.m_oData.m_oAllowedValues = {}; - } + }; this.UpdateFields = function () { @@ -120,10 +121,10 @@ function WizardHelper(sClass, sFormPrefix, sState) // For each "refreshed" field, asynchronously trigger a change in case there are dependent fields to update for(i=0; i