From ec19ef982e87154247e4fe3c2d3ecf34465b3d35 Mon Sep 17 00:00:00 2001 From: Denis Flaven Date: Tue, 13 Dec 2011 14:37:31 +0000 Subject: [PATCH] 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. SVN:trunk[1714] --- application/cmdbabstract.class.inc.php | 6 +- application/ui.extkeywidget.class.inc.php | 50 +++++++++++--- core/dbobjectsearch.class.php | 5 ++ core/dbobjectset.class.php | 39 +++++++++++ core/expression.class.inc.php | 84 ++++++++++++++++++++++- dictionaries/fr.dictionary.itop.ui.php | 1 + js/extkeywidget.js | 21 +++++- pages/ajax.render.php | 38 ++++++++-- 8 files changed, 222 insertions(+), 22 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index fb0edca6b..e64e6f1b3 100644 --- a/application/cmdbabstract.class.inc.php +++ b/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 .= ''; - $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)) { diff --git a/application/ui.extkeywidget.class.inc.php b/application/ui.extkeywidget.class.inc.php index f88f51459..624903882 100644 --- a/application/ui.extkeywidget.class.inc.php +++ b/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 .= "\n"; $oPage->add_ready_script( <<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 = "

$sMessage

"; $('#$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( <<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 = "

$sMessage

"; $('#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 = '
'; - $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 .= "
iId}\" OnSubmit=\"return oACWidget_{$this->iId}.DoOk();\">\n"; $sHTML .= "
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); diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index b426345cc..5981de40d 100644 --- a/core/dbobjectsearch.class.php +++ b/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); diff --git a/core/dbobjectset.class.php b/core/dbobjectset.class.php index c7567608c..43b3c1e6d 100644 --- a/core/dbobjectset.class.php +++ b/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; + } } /** diff --git a/core/expression.class.inc.php b/core/expression.class.inc.php index b592a69cb..e7df0c033 100644 --- a/core/expression.class.inc.php +++ b/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 = or = : + * Could be extended to support = + */ + 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) diff --git a/dictionaries/fr.dictionary.itop.ui.php b/dictionaries/fr.dictionary.itop.ui.php index 3d5ca2e36..1a9edff89 100644 --- a/dictionaries/fr.dictionary.itop.ui.php +++ b/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', diff --git a/js/extkeywidget.js b/js/extkeywidget.js index a2629ace9..9f5b0ca2e 100644 --- a/js/extkeywidget.js +++ b/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('
'); @@ -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' } diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 5fe40e0ac..f86616811 100644 --- a/pages/ajax.render.php +++ b/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;