浏览代码

Bug fix: apply the AllowedValues constraints(as default values) when selecting elements via the "magnifier" button or creating an new element via the "plus" button.

git-svn-id: http://svn.code.sf.net/p/itop/code/trunk@1714 a333f486-631f-4898-b8df-5754b55c2be0
dflaven 13 年之前
父节点
当前提交
3faa4ad8c5

+ 4 - 2
application/cmdbabstract.class.inc.php

@@ -1445,12 +1445,14 @@ EOF
 			$aMapCriteria[$aCriteria['filtercode']][] = array('value' => $aCriteria['value'], 'opcode' => $aCriteria['opcode']);
 		}
 		$aList = MetaModel::GetZListItems($sClassName, 'standard_search');
+		$aConsts = $oSet->ListConstantFields(); // Some fields are constants based on the query/context
+		$sClassAlias = $oSet->GetFilter()->GetClassAlias();
 		foreach($aList as $sFilterCode)
 		{
 			//$oAppContext->Reset($sFilterCode); // Make sure the same parameter will not be passed twice
 			$sHtml .= '<span style="white-space: nowrap;padding:5px;display:inline-block;">';
-			$sFilterValue = '';
-			$sFilterValue = utils::ReadParam($sFilterCode, '', false, 'raw_data');
+			$sFilterValue = isset($aConsts[$sClassAlias][$sFilterCode]) ? $aConsts[$sClassAlias][$sFilterCode] : '';
+			$sFilterValue = utils::ReadParam($sFilterCode, $sFilterValue, false, 'raw_data');
 			$sFilterOpCode = null; // Use the default 'loose' OpCode
 			if (empty($sFilterValue))
 			{

+ 40 - 10
application/ui.extkeywidget.class.inc.php

@@ -65,6 +65,7 @@ class UIExtKeyWidget
 {
 	protected $iId;
 	protected $sTargetClass;
+	protected $sAttCode;
 	
 	//public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '')
 	static public function DisplayFromAttCode($oPage, $sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName = '', $sFormPrefix = '', $aArgs, $bSearchMode = false)
@@ -81,14 +82,15 @@ class UIExtKeyWidget
 		{
 			$sDisplayStyle = 'select'; // In search mode, always use a drop-down list
 		}
-		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId);
+		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode);
 		return $oWidget->Display($oPage, $iMaxComboLength, $bAllowTargetCreation, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sFieldName, $sFormPrefix, $aArgs, $bSearchMode, $sDisplayStyle);
 	}
 
-	public function __construct($sTargetClass, $iInputId)
+	public function __construct($sTargetClass, $iInputId, $sAttCode = '')
 	{
 		$this->sTargetClass = $sTargetClass;
 		$this->iId = $iInputId;
+		$this->sAttCode = $sAttCode;
 	}
 	
 	/**
@@ -182,7 +184,7 @@ class UIExtKeyWidget
 				$sHTMLValue .= "</select>\n";
 				$oPage->add_ready_script(
 <<<EOF
-		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper);
+		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', true, $sWizHelper, '{$this->sAttCode}');
 		oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
 		$('#$this->iId').bind('update', function() { oACWidget_{$this->iId}.Update(); } );
 		$('#$this->iId').bind('change', function() { $(this).trigger('extkeychange') } );
@@ -217,7 +219,7 @@ EOF
 			// Scripts to start the autocomplete and bind some events to it
 			$oPage->add_ready_script(
 <<<EOF
-		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper);
+		oACWidget_{$this->iId} = new ExtKeyWidget('{$this->iId}', '{$this->sTargetClass}', '$sFilter', '$sTitle', false, $sWizHelper, '{$this->sAttCode}');
 		oACWidget_{$this->iId}.emptyHtml = "<div style=\"background: #fff; border:0; text-align:center; vertical-align:middle;\"><p>$sMessage</p></div>";
 		$('#label_$this->iId').autocomplete(GetAbsoluteUrlAppRoot()+'pages/ajax.render.php', { scroll:true, minChars:{$iMinChars}, autoFill:false, matchContains:true, mustMatch: true, keyHolder:'#{$this->iId}', extraParams:{operation:'ac_extkey', sTargetClass:'{$this->sTargetClass}',sFilter:'$sFilter', json: function() { return $sWizHelperJSON; } }});
 		$('#label_$this->iId').keyup(function() { if ($(this).val() == '') { $('#$this->iId').val(''); } } ); // Useful for search forms: empty value in the "label", means no value, immediatly !
@@ -262,13 +264,24 @@ EOF
 		return $sHTMLValue;
 	}
 	
-	public function GetSearchDialog(WebPage $oPage, $sTitle)
+	public function GetSearchDialog(WebPage $oPage, $sTitle, $oCurrObject = null)
 	{
 		$sHTML = '<div class="wizContainer" style="vertical-align:top;"><div id="dc_'.$this->iId.'">';
 
-		$oFilter = new DBObjectSearch($this->sTargetClass);
-		$oSet = new CMDBObjectSet($oFilter);
-		$oBlock = new DisplayBlock($oFilter, 'search', false);
+		if ( ($oCurrObject != null) && ($this->sAttCode != ''))
+		{
+			$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
+			$aParams = array('query_params' => array('this' => $oCurrObject));
+			$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aParams);
+			$oFilter = $oSet->GetFilter();
+		}
+		else
+		{
+			$aParam = array();
+			$oFilter = new DBObjectSearch($this->sTargetClass);
+			$oSet = new CMDBObjectSet($oFilter);
+		}
+		$oBlock = new DisplayBlock($oFilter, 'search', false, $aParams);
 		$sHTML .= $oBlock->GetDisplay($oPage, $this->iId, array('open' => true, 'currentId' => $this->iId));
 		$sHTML .= "<form id=\"fr_{$this->iId}\" OnSubmit=\"return oACWidget_{$this->iId}.DoOk();\">\n";
 		$sHTML .= "<div id=\"dr_{$this->iId}\" style=\"vertical-align:top;background: #fff;height:100%;overflow:auto;padding:0;border:0;\">\n";
@@ -353,7 +366,7 @@ EOF
 	/**
 	 * Get the form to create a new object of the 'target' class
 	 */
-	public function GetObjectCreationForm(WebPage $oPage)
+	public function GetObjectCreationForm(WebPage $oPage, $oCurrObject)
 	{
 		// Set all the default values in an object and clone this "default" object
 		$oNewObj = MetaModel::NewObject($this->sTargetClass);
@@ -362,7 +375,24 @@ EOF
 		$oAppContext = new ApplicationContext();
 		$oAppContext->InitObjectFromContext($oNewObj);
 
-		// 2nd - set values from the page argument 'default'
+		// 2nd set the default values from the constraint on the external key... if any
+		if ( ($oCurrObject != null) && ($this->sAttCode != ''))
+		{
+			$oAttDef = MetaModel::GetAttributeDef(get_class($oCurrObject), $this->sAttCode);
+			$aParams = array('this' => $oCurrObject);
+			$oSet = $oAttDef->GetAllowedValuesAsObjectSet($aParams);
+			$aConsts = $oSet->ListConstantFields();
+			$sClassAlias = $oSet->GetFilter()->GetClassAlias();
+			if (isset($aConsts[$sClassAlias]))
+			{
+				foreach($aConsts[$sClassAlias] as $sAttCode => $value)
+				{
+					$oNewObj->Set($sAttCode, $value);
+				}
+			}
+		}
+		
+		// 3rd - set values from the page argument 'default'
 		$oNewObj->UpdateObjectFromArg('default');
 
 		$sDialogTitle = addslashes($this->sTitle);

+ 5 - 0
core/dbobjectsearch.class.php

@@ -742,6 +742,11 @@ class DBObjectSearch
 		return $this->m_aParams;
 	}
 
+	public function ListConstantFields()
+	{
+		return $this->m_oSearchCondition->ListConstantFields();
+	}
+	
 	public function RenderCondition()
 	{
 		return $this->m_oSearchCondition->Render($this->m_aParams, false);

+ 39 - 0
core/dbobjectset.class.php

@@ -687,6 +687,45 @@ class DBObjectSet
 		$this->Rewind();
 		return $oCommonObj;
 	}
+
+	/**
+	 * List the constant fields (and their value) in the given query
+	 * @return Hash [Alias][AttCode] => value
+	 */
+	public function ListConstantFields()
+	{
+		$aScalarArgs = array();
+		foreach($this->m_aArgs as $sArgName => $value)
+		{
+			if (MetaModel::IsValidObject($value))
+			{
+				$aScalarArgs = array_merge($aScalarArgs, $value->ToArgs($sArgName));
+			}
+			else
+			{
+				$aScalarArgs[$sArgName] = (string) $value;
+			}
+		}
+		$aScalarArgs['current_contact_id'] = UserRights::GetContactId();
+		
+		$aConst = $this->m_oFilter->ListConstantFields();
+		
+		foreach($aConst as $sClassAlias => $aVals)
+		{
+			foreach($aVals as $sCode => $oExpr)
+			{
+				if ($oExpr instanceof ScalarExpression)
+				{
+					$aConst[$sClassAlias][$sCode] = $oExpr->GetValue();
+				}
+				else //Variable
+				{
+					$aConst[$sClassAlias][$sCode] = $aScalarArgs[$oExpr->GetName()];
+				}
+			}
+		}
+		return $aConst;		
+	}
 }
 
 /**

+ 81 - 3
core/expression.class.inc.php

@@ -40,7 +40,10 @@ abstract class Expression
 	abstract public function ListRequiredFields();
 
 	abstract public function IsTrue();
-
+	
+	// recursively builds an array of [classAlias][fieldName] => value
+	abstract public function ListConstantFields();
+	
 	public function RequiresField($sClass, $sFieldName)
 	{
 		// #@# todo - optimize : this is called quite often when building a single query !
@@ -122,6 +125,11 @@ class SQLExpression extends Expression
 		return array();
 	}
 	
+	public function ListConstantFields()
+	{
+		return array();
+	}
+	
 	public function RenameParam($sOldName, $sNewName)
 	{
 		// Do nothing, since there is nothing to rename
@@ -164,11 +172,11 @@ class BinaryExpression extends Expression
 		// return true if we are certain that it will be true
 		if ($this->m_sOperator == 'AND')
 		{
-			if ($this->m_oLeftExpr->IsTrue() && $this->m_oLeftExpr->IsTrue()) return true;
+			if ($this->m_oLeftExpr->IsTrue() && $this->m_oRightExpr->IsTrue()) return true;
 		}
 		return false;
 	}
-
+	
 	public function GetLeftExpr()
 	{
 		return $this->m_oLeftExpr;
@@ -213,6 +221,36 @@ class BinaryExpression extends Expression
 		return array_merge($aLeft, $aRight);
 	}
 	
+	
+	/**
+	 * List all constant expression of the form <field> = <scalar> or <field> = :<variable>
+	 * Could be extended to support <field> = <function><constant_expression>
+	 */
+	public function ListConstantFields()
+	{
+		$aResult = array();
+		if ($this->m_sOperator == '=')
+		{
+			if (($this->m_oLeftExpr instanceof FieldExpression) && ($this->m_oRightExpr instanceof ScalarExpression))
+			{
+				$aResult[$this->m_oLeftExpr->GetParent()][$this->m_oLeftExpr->GetName()] = $this->m_oRightExpr;
+			}
+			else if (($this->m_oRightExpr instanceof FieldExpression) && ($this->m_oLeftExpr instanceof ScalarExpression))
+			{
+				$aResult[$this->m_oRightExpr->GetParent()][$this->m_oRightExpr->GetName()] = $this->m_oLeftExpr;
+			}
+			else if (($this->m_oLeftExpr instanceof FieldExpression) && ($this->m_oRightExpr instanceof VariableExpression))
+			{
+				$aResult[$this->m_oLeftExpr->GetParent()][$this->m_oLeftExpr->GetName()] = $this->m_oRightExpr;
+			}
+			else if (($this->m_oRightExpr instanceof FieldExpression) && ($this->m_oLeftExpr instanceof VariableExpression))
+			{
+				$aResult[$this->m_oRightExpr->GetParent()][$this->m_oRightExpr->GetName()] = $this->m_oLeftExpr;
+			}
+		}
+		return $aResult;
+	}
+	
 	public function RenameParam($sOldName, $sNewName)
 	{
 		$this->GetLeftExpr()->RenameParam($sOldName, $sNewName);
@@ -269,6 +307,11 @@ class UnaryExpression extends Expression
 	{
 		return array();
 	}
+
+	public function ListConstantFields()
+	{
+		return array();
+	}
 	
 	public function RenameParam($sOldName, $sNewName)
 	{
@@ -529,6 +572,16 @@ class ListExpression extends Expression
 		return $aRes;
 	}
 	
+	public function ListConstantFields()
+	{
+		$aRes = array();
+		foreach ($this->m_aExpressions as $oExpr)
+		{
+			$aRes = array_merge($aRes, $oExpr->ListConstantFields());
+		}
+		return $aRes;
+	}
+	
 	public function RenameParam($sOldName, $sNewName)
 	{
 		$aRes = array();
@@ -606,6 +659,16 @@ class FunctionExpression extends Expression
 		return $aRes;
 	}
 	
+	public function ListConstantFields()
+	{
+		$aRes = array();
+		foreach ($this->m_aArgs as $oExpr)
+		{
+			$aRes = array_merge($aRes, $oExpr->ListConstantFields());
+		}
+		return $aRes;
+	}
+	
 	public function RenameParam($sOldName, $sNewName)
 	{
 		foreach ($this->m_aArgs as $key => $oExpr)
@@ -662,6 +725,11 @@ class IntervalExpression extends Expression
 	{
 		return array();
 	}
+
+	public function ListConstantFields()
+	{
+		return array();
+	}
 	
 	public function RenameParam($sOldName, $sNewName)
 	{
@@ -730,6 +798,16 @@ class CharConcatExpression extends Expression
 		return $aRes;
 	}
 
+	public function ListConstantFields()
+	{
+		$aRes = array();
+		foreach ($this->m_aExpressions as $oExpr)
+		{
+			$aRes = array_merge($aRes, $oExpr->ListConstantFields());
+		}
+		return $aRes;
+	}
+
 	public function RenameParam($sOldName, $sNewName)
 	{
 		foreach ($this->m_aExpressions as $key => $oExpr)

+ 1 - 0
dictionaries/fr.dictionary.itop.ui.php

@@ -716,6 +716,7 @@ Lors de l\'association à un déclencheur, on attribue à chaque action un numé
 	'UI:DisplayThisMessageAtStartup' => 'Afficher ce message au démarrage',
 	'UI:RelationshipGraph' => 'Vue graphique',
 	'UI:RelationshipList' => 'Liste',
+	'UI:ElementsDisplayed' => 'Eléments Affichés',
 	'UI:OperationCancelled' => 'Opération Annulée',
 	'Portal:Title' => 'Portail utilisateur iTop',
 	'Portal:Refresh' => 'Rafraîchir',

+ 20 - 1
js/extkeywidget.js

@@ -13,12 +13,13 @@
 //   along with this program; if not, write to the Free Software
 //   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
-function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper)
+function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper, sAttCode)
 {
 	this.id = id;
 	this.sTargetClass = sTargetClass;
 	this.sFilter = sFilter;
 	this.sTitle = sTitle;
+	this.sAttCode = sAttCode;
 	this.emptyHtml = ''; // content to be displayed when the search results are empty (when opening the dialog) 
 	this.emptyOnClose = true; // Workaround for the JQuery dialog being very slow when opening and closing if the content contains many INPUT tags
 	this.oWizardHelper = oWizHelper;
@@ -61,10 +62,22 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 		var theMap = { sAttCode: me.sAttCode,
 				   iInputId: me.id,
 				   sTitle: me.sTitle,
+				   sAttCode: me.sAttCode,
 				   sTargetClass: me.sTargetClass,
 				   operation: 'objectSearchForm'
 				 }
 	
+		if (me.oWizardHelper == null)
+		{
+			theMap['json'] = '';
+		}
+		else
+		{
+			// Not inside a "search form", updating a real object
+			me.oWizardHelper.UpdateWizard();
+			theMap['json'] = me.oWizardHelper.ToJSON();
+		}
+
 		// Make sure that we cancel any pending request before issuing another
 		// since responses may arrive in arbitrary order
 		me.StopPendingRequest();
@@ -152,6 +165,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 		
 		theMap['sRemoteClass'] = theMap['class'];  // swap 'class' (defined in the form) and 'remoteClass'
 		theMap.operation = 'searchObjectsToSelect'; // Override what is defined in the form itself
+		theMap.sAttCode = me.sAttCode,
 		
 		sSearchAreaId = '#dr_'+me.id;
 		//$(sSearchAreaId).html('<div style="text-align:center;width:100%;height:24px;vertical-align:middle;"><img src="../images/indicator.gif" /></div>');
@@ -200,6 +214,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 		var theMap = { sTargetClass: me.sTargetClass,
 				   iInputId: me.id,
 				   iObjectId: iObjectId,
+				   sAttCode: me.sAttCode,
 				   operation: 'getObjectName'
 				 }
 	
@@ -262,6 +277,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 		me.oWizardHelper.UpdateWizard();
 		var theMap = { sTargetClass: me.sTargetClass,
 				   iInputId: me.id,
+				   sAttCode: me.sAttCode,
 				   'json': me.oWizardHelper.ToJSON(),
 				   operation: 'objectCreationForm'
 				 }
@@ -323,6 +339,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 			$('#'+sFormId).block();
 			var theMap = { sTargetClass: me.sTargetClass,
 					   iInputId: me.id,
+					   sAttCode: me.sAttCode,
 					   'json': me.oWizardHelper.ToJSON()
 					 }
 
@@ -403,6 +420,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 		var theMap = { sTargetClass: me.sTargetClass,
 				   	   sInputId: me.id,
 				   	   sFilter: me.sFilter,
+				   	   sAttCode: me.sAttCode,
 				   	   value: $('#'+me.id).val()
 					};
 	
@@ -484,6 +502,7 @@ function ExtKeyWidget(id, sTargetClass, sFilter, sTitle, bSelectMode, oWizHelper
 		var theMap = { sTargetClass: me.sTargetClass,
 				   iInputId: me.id,
 				   iObjectId: iObjectId,
+				   sAttCode: me.sAttCode,
 				   operation: 'getObjectName'
 				 }
 	

+ 32 - 6
pages/ajax.render.php

@@ -192,6 +192,7 @@ try
 		$sRemoteClass = utils::ReadParam('sRemoteClass', '', false, 'class');
 		$sFilter = utils::ReadParam('sFilter', '', false, 'raw_data');
 		$sJson = utils::ReadParam('json', '', false, 'raw_data');
+		$sAttCode = utils::ReadParam('sAttCode', '');
 		if (!empty($sJson))
 		{
 			$oWizardHelper = WizardHelper::FromJSON($sJson);
@@ -202,7 +203,7 @@ try
 			// Search form: no current object
 			$oObj = null;
 		}
-		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId);
+		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode);
 		$oWidget->SearchObjectsToSelect($oPage, $sFilter, $sRemoteClass, $oObj);	
 		break;
 	
@@ -233,16 +234,40 @@ try
 		$sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class');
 		$iInputId = utils::ReadParam('iInputId', '');
 		$sTitle = utils::ReadParam('sTitle', '', false, 'raw_data');
-		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId);
-		$oWidget->GetSearchDialog($oPage, $sTitle);
+		$sAttCode = utils::ReadParam('sAttCode', '');
+		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode);
+		$sJson = utils::ReadParam('json', '', false, 'raw_data');
+		if (!empty($sJson))
+		{
+			$oWizardHelper = WizardHelper::FromJSON($sJson);
+			$oObj = $oWizardHelper->GetTargetObject();
+		}
+		else
+		{
+			// Search form: no current object
+			$oObj = null;
+		}
+		$oWidget->GetSearchDialog($oPage, $sTitle, $oObj);
 		break;
 
 		// ui.extkeywidget
 		case 'objectCreationForm':
 		$sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class');
 		$iInputId = utils::ReadParam('iInputId', '');
-		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId);
-		$oWidget->GetObjectCreationForm($oPage);
+		$sAttCode = utils::ReadParam('sAttCode', '');
+		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode);
+		$sJson = utils::ReadParam('json', '', false, 'raw_data');
+		if (!empty($sJson))
+		{
+			$oWizardHelper = WizardHelper::FromJSON($sJson);
+			$oObj = $oWizardHelper->GetTargetObject();
+		}
+		else
+		{
+			// Search form: no current object
+			$oObj = null;
+		}
+		$oWidget->GetObjectCreationForm($oPage, $oObj);
 		break;
 		
 		// ui.extkeywidget
@@ -250,7 +275,8 @@ try
 		$sTargetClass = utils::ReadParam('sTargetClass', '', false, 'class');
 		$iInputId = utils::ReadParam('iInputId', '');
 		$sFormPrefix = utils::ReadParam('sFormPrefix', '');
-		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId);
+		$sAttCode = utils::ReadParam('sAttCode', '');
+		$oWidget = new UIExtKeyWidget($sTargetClass, $iInputId, $sAttCode);
 		$aResult = $oWidget->DoCreateObject($oPage);
 		echo json_encode($aResult);
 		break;