Преглед изворни кода

#704: preserve the content of a "linkedset" when changing the initial state of the object being created !

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@2737 a333f486-631f-4898-b8df-5754b55c2be0
dflaven пре 12 година
родитељ
комит
24a80303c6

+ 15 - 2
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 = "<span id=\"field_{$sInputId}\">".self::GetFormElementForField($oPage, $sClass, $sAttCode, $oAttDef, $oValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs).'</span>';
-				$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('');

+ 22 - 8
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 .= "<div id=\"linkedset_{$this->m_sAttCode}{$this->m_sNameSuffix}\">\n";
+		$sHtmlValue .= "<input type=\"hidden\" id=\"{$sFormPrefix}{$this->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(<<<EOF
-		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);
+		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 .= "<span style=\"float:left;\">&nbsp;&nbsp;&nbsp;<img src=\"../images/tv-item-last.gif\">&nbsp;&nbsp;<input id=\"{$this->m_sAttCode}{$this->m_sNameSuffix}_btnRemove\" type=\"button\" value=\"".Dict::S('UI:RemoveLinkedObjectsOf_Class')."\" onClick=\"oWidget{$this->m_iInputId}.RemoveSelected();\" >";

+ 1 - 1
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;} 

+ 43 - 2
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);
+	};
 }

+ 22 - 23
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<aRefreshed.length; i++)
 		{
-			var sString = "$('#"+aRefreshed[i]+"').trigger('change').trigger('update');"
+			var sString = "$('#"+aRefreshed[i]+"').trigger('change').trigger('update');";
 			window.setTimeout(sString, 1); // Synchronous 'trigger' does nothing, call it asynchronously
 		}
-	}
+	};
 	
 	this.UpdateWizard = function ()
 	{
@@ -134,16 +135,13 @@ function WizardHelper(sClass, sFormPrefix, sState)
 			//console.log(sFieldCode);
 			this.UpdateCurrentValue(sCleanFieldCode);
 		}
-		// Remove unnecessary stuff
-		this.m_oData.m_oDefaultValue = {};
-		this.m_oData.m_oAllowedValues = {};
-	}
+	};
 	
 	this.UpdateWizardToJSON = function ()
 	{
 		this.UpdateWizard();
-		return this.ToJSON()
-	}
+		return this.ToJSON();
+	};
 	
 	this.AjaxQueryServer = function ()
 	{
@@ -159,7 +157,7 @@ function WizardHelper(sClass, sFormPrefix, sState)
 				//console.log(oWizardHelper);
 				//$('#wizStep'+ G_iCurrentStep).unblock( {fadeOut: 0} );
 			});
-	}
+	};
 	
 	this.Preview = function (divId)
 	{
@@ -170,10 +168,11 @@ function WizardHelper(sClass, sFormPrefix, sState)
 			function(responseText, textStatus, XMLHttpRequest){
 				$('#wizStep'+ G_iCurrentStep).unblock( {fadeOut: 0} );
 			});
-	}
+	};
 	
 	this.UpdateCurrentValue = function (sFieldCode)
 	{
+		$('#'+this.m_oData.m_oFieldsMap[sFieldCode]).trigger('update_value'); // Give the widget a chance to update its value (if it is aware of this event)
 		value = $('#'+this.m_oData.m_oFieldsMap[sFieldCode]).val();
 		if (value == '')
 		{
@@ -181,7 +180,7 @@ function WizardHelper(sClass, sFormPrefix, sState)
 		}
 		this.m_oData.m_oCurrentValues[sFieldCode] = value;
 		return value;		
-	}
+	};
 
 	this.UpdateDependentFields = function(aFieldNames)
 	{
@@ -197,7 +196,7 @@ function WizardHelper(sClass, sFormPrefix, sState)
 			index++;
 		}
 		this.AjaxQueryServer();
-	}
+	};
 	
 	this.ReloadObjectCreationForm = function(sFormId, sTargetState)
 	{
@@ -224,5 +223,5 @@ function WizardHelper(sClass, sFormPrefix, sState)
 				$('#'+sFormId).unblock();
 			}
 		);		
-	}
+	};
 }