From a0900cd732e716334c390f7fb79c36aff9a36682 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Wed, 8 Jun 2011 13:30:56 +0000 Subject: [PATCH] Optimization: do not load the full set of items when it comes to displaying an autocomplete! SVN:trunk[1275] --- application/cmdbabstract.class.inc.php | 106 +++++++++++++--------- application/ui.extkeywidget.class.inc.php | 36 ++++---- core/attributedef.class.inc.php | 8 ++ core/dbobjectset.class.php | 5 +- core/metamodel.class.php | 5 + core/valuesetdef.class.inc.php | 16 ++++ pages/ajax.render.php | 18 ++-- 7 files changed, 123 insertions(+), 71 deletions(-) diff --git a/application/cmdbabstract.class.inc.php b/application/cmdbabstract.class.inc.php index c5b900e55..9cf9146b8 100644 --- a/application/cmdbabstract.class.inc.php +++ b/application/cmdbabstract.class.inc.php @@ -1156,47 +1156,49 @@ EOF } } } - $aAllowedValues = MetaModel::GetAllowedValues_flt($sClassName, $sFilterCode, $aExtraParams); - if ($aAllowedValues != null) - { - $oAttDef = MetaModel::GetAttributeDef($sClassName, $sFilterCode); - if ($oAttDef->IsExternalKey()) - { - $iFieldSize = $oAttDef->GetMaxSize(); - $iMaxComboLength = $oAttDef->GetMaximumComboLength(); - $oWidget = new UIExtKeyWidget($sFilterCode, $sClassName, $oAttDef->GetLabel(), $aAllowedValues, $sFilterValue, 'search_'.$sFilterCode, false, '', '', ''); - $sHtml .= " "; - $sHtml .= $oWidget->Display($oPage, $aExtraParams, true /* bSearchMode */); - } - else - { - //Enum field or external key, display a combo - $sValue = "\n"; - $sHtml .= " $sValue\n"; - } - unset($aExtraParams[$sFilterCode]); + $oAttDef = MetaModel::GetAttributeDef($sClassName, $sFilterCode); + if ($oAttDef->IsExternalKey()) + { + $sTargetClass = $oAttDef->GetTargetClass(); + $oAllowedValues = new DBObjectSet(new DBObjectSearch($sTargetClass)); + + $iFieldSize = $oAttDef->GetMaxSize(); + $iMaxComboLength = $oAttDef->GetMaximumComboLength(); + $oWidget = new UIExtKeyWidget($sFilterCode, $sClassName, $oAttDef->GetLabel(), $oAllowedValues, $sFilterValue, 'search_'.$sFilterCode, false, '', '', ''); + $sHtml .= " "; + $sHtml .= $oWidget->Display($oPage, $aExtraParams, true /* bSearchMode */); } else { - // Any value is possible, display an input box - $sHtml .= " \n"; - unset($aExtraParams[$sFilterCode]); + $aAllowedValues = MetaModel::GetAllowedValues_flt($sClassName, $sFilterCode, $aExtraParams); + if (is_null($aAllowedValues)) + { + // Any value is possible, display an input box + $sHtml .= " \n"; + } + else + { + //Enum field, display a combo + $sValue = "\n"; + $sHtml .= " $sValue\n"; + } } + unset($aExtraParams[$sFilterCode]); $index++; $sHtml .= ' '; } @@ -1406,10 +1408,10 @@ EOF $aEventsList[] ='validate'; $aEventsList[] ='change'; - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs); $iFieldSize = $oAttDef->GetMaxSize(); $iMaxComboLength = $oAttDef->GetMaximumComboLength(); - $oWidget = new UIExtKeyWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $aAllowedValues, $value, $iId, $bMandatory, $sNameSuffix, $sFieldPrefix, $sFormPrefix); + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, $oAttDef->GetLabel(), $oAllowedValues, $value, $iId, $bMandatory, $sNameSuffix, $sFieldPrefix, $sFormPrefix); $sHTMLValue = $oWidget->Display($oPage, $aArgs); $sHTMLValue .= "\n"; break; @@ -1777,20 +1779,36 @@ EOF // Now fill-in the fields with default/supplied values foreach($aList as $sAttCode) { - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); if (isset($aArgs['default'][$sAttCode])) { $oObj->Set($sAttCode, $aArgs['default'][$sAttCode]); } - elseif (count($aAllowedValues) == 1) + else { - // If the field is mandatory, set it to the only possible value $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); + + // If the field is mandatory, set it to the only possible value $iFlags = $oObj->GetAttributeFlags($sAttCode); - if ( (!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY)) + if ((!$oAttDef->IsNullAllowed()) || ($iFlags & OPT_ATT_MANDATORY)) { - $aValues = array_keys($aAllowedValues); - $oObj->Set($sAttCode, $aValues[0]); + if ($oAttDef->IsExternalKey()) + { + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs); + if ($oAllowedValues->Count() == 1) + { + $oRemoteObj = $oAllowedValues->Fetch(); + $oObj->Set($sAttCode, $oRemoteObj->GetKey()); + } + } + else + { + $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, $aArgs); + if (count($aAllowedValues) == 1) + { + $aValues = array_keys($aAllowedValues); + $oObj->Set($sAttCode, $aValues[0]); + } + } } } } diff --git a/application/ui.extkeywidget.class.inc.php b/application/ui.extkeywidget.class.inc.php index ac55cc8d0..5f88c35a4 100644 --- a/application/ui.extkeywidget.class.inc.php +++ b/application/ui.extkeywidget.class.inc.php @@ -68,8 +68,10 @@ class UIExtKeyWidget protected $sNameSuffix; protected $iId; protected $sTitle; + + protected $oAllowedValues = null; - public function __construct($sAttCode, $sClass, $sTitle, $aAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '') + public function __construct($sAttCode, $sClass, $sTitle, $oAllowedValues, $value, $iInputId, $bMandatory, $sNameSuffix = '', $sFieldPrefix = '', $sFormPrefix = '') { self::$iWidgetIndex++; $this->sAttCode = $sAttCode; @@ -77,7 +79,7 @@ class UIExtKeyWidget $this->oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $this->sNameSuffix = $sNameSuffix; $this->iId = $iInputId; - $this->aAllowedValues = $aAllowedValues; + $this->oAllowedValues = $oAllowedValues; $this->value = $value; $this->sFieldPrefix = $sFieldPrefix; $this->sTargetClass = $this->oAttDef->GetTargetClass(); @@ -110,7 +112,11 @@ class UIExtKeyWidget { $sWizHelper = 'oWizardHelper'.$this->sFormPrefix; } - if (count($this->aAllowedValues) < $this->oAttDef->GetMaximumComboLength()) + if (is_null($this->oAllowedValues)) + { + throw new Exception('Implementation: null value for allowed values definition'); + } + elseif ($this->oAllowedValues->Count() < $this->oAttDef->GetMaximumComboLength()) { // Few choices, use a normal 'select' $sSelectMode = 'true'; @@ -127,9 +133,13 @@ class UIExtKeyWidget { $sHTMLValue .= "\n"; } - foreach($this->aAllowedValues as $key => $display_value) + $this->oAllowedValues->Rewind(); + while($oObj = $this->oAllowedValues->Fetch()) { - if ((count($this->aAllowedValues) == 1) && ($this->bMandatory == 'true') ) + $key = $oObj->GetKey(); + $display_value = $oObj->Get('friendlyname'); + + if (($this->oAllowedValues->Count() == 1) && ($this->bMandatory == 'true') ) { // When there is only once choice, select it by default $sSelected = ' selected'; @@ -168,7 +178,7 @@ EOF $iFieldSize = $this->oAttDef->GetMaxSize(); // the input for the auto-complete - $sHTMLValue = "aAllowedValues)."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/> "; + $sHTMLValue = "oAllowedValues->Count()."\" type=\"text\" id=\"label_$this->iId\" size=\"30\" maxlength=\"$iFieldSize\" value=\"$sDisplayValue\"/> "; $sHTMLValue .= "iId}.Search();\">iId}\" style=\"border:0;vertical-align:middle;\" src=\"../images/mini_search.gif\" /> "; // another hidden input to store & pass the object's Id @@ -236,19 +246,11 @@ EOF */ public function SearchObjectsToSelect(WebPage $oP, $sTargetClass = '') { - if ($sTargetClass != '') + if (is_null($this->oAllowedValues)) { - // assert(MetaModel::IsParentClass($this->m_sRemoteClass, $sRemoteClass)); - $oFilter = new DBObjectSearch($sTargetClass); + throw new Exception('Implementation: null value for allowed values definition'); } - else - { - // No remote class specified use the one defined in the linkedset - $oFilter = new DBObjectSearch($this->sTargetClass); - } - $oFilter->AddCondition('id', array_keys($this->aAllowedValues), 'IN'); - $oSet = new CMDBObjectSet($oFilter); - $oBlock = new DisplayBlock($oFilter, 'list', false); + $oBlock = new DisplayBlock($this->oAllowedValues->GetFilter(), 'list', false); $oBlock->Display($oP, $this->iId, array('menu' => false, 'selection_mode' => true, 'selection_type' => 'single', 'display_limit' => false)); // Don't display the 'Actions' menu on the results } diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index 1a0093827..691f15483 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -2339,6 +2339,7 @@ class AttributeExternalKey extends AttributeDBFieldVoid public function GetAllowedValues($aArgs = array(), $sContains = '') { + //throw new Exception("GetAllowedValues on ext key has been deprecated"); try { return parent::GetAllowedValues($aArgs, $sContains); @@ -2351,6 +2352,13 @@ class AttributeExternalKey extends AttributeDBFieldVoid } } + public function GetAllowedValuesAsObjectSet($aArgs = array(), $sContains = '') + { + $oValSetDef = $this->GetValuesDef(); + $oSet = $oValSetDef->ToObjectSet($aArgs, $sContains); + return $oSet; + } + public function GetDeletionPropagationOption() { return $this->Get("on_target_delete"); diff --git a/core/dbobjectset.class.php b/core/dbobjectset.class.php index d5a52533b..24cbf7dec 100644 --- a/core/dbobjectset.class.php +++ b/core/dbobjectset.class.php @@ -353,7 +353,10 @@ class DBObjectSet public function Rewind() { - $this->Seek(0); + if ($this->m_bLoaded) + { + $this->Seek(0); + } } public function Seek($iRow) diff --git a/core/metamodel.class.php b/core/metamodel.class.php index 0f8bc8c8e..ad7d14e53 100644 --- a/core/metamodel.class.php +++ b/core/metamodel.class.php @@ -1024,6 +1024,11 @@ abstract class MetaModel return $oFltDef->GetAllowedValues($aArgs, $sContains); } + public static function GetAllowedValuesAsObjectSet($sClass, $sAttCode, $aArgs = array(), $sContains = '') + { + $oAttDef = self::GetAttributeDef($sClass, $sAttCode); + return $oAttDef->GetAllowedValuesAsObjectSet($aArgs, $sContains); + } // // Businezz model declaration verbs (should be static) // diff --git a/core/valuesetdef.class.inc.php b/core/valuesetdef.class.inc.php index ee9bfddec..ce92d2c84 100644 --- a/core/valuesetdef.class.inc.php +++ b/core/valuesetdef.class.inc.php @@ -101,6 +101,22 @@ class ValueSetObjects extends ValueSetDefinition $this->m_bAllowAllData = $bAllowAllData; } + + public function ToObjectSet($aArgs = array(), $sContains = '') + { + if ($this->m_bAllowAllData) + { + $oFilter = DBObjectSearch::FromOQL_AllData($this->m_sFilterExpr); + } + else + { + $oFilter = DBObjectSearch::FromOQL($this->m_sFilterExpr); + } + + return new DBObjectSet($oFilter, $this->m_aOrderBy, $aArgs); + } + + protected function LoadValues($aArgs) { $this->m_aValues = array(); diff --git a/pages/ajax.render.php b/pages/ajax.render.php index 78ad2e5ce..1ee1f151b 100644 --- a/pages/ajax.render.php +++ b/pages/ajax.render.php @@ -91,8 +91,8 @@ try $oObj = null; $currentValue = ''; } - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj)); - $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $currentValue, $iInputId, false, $sSuffix, ''); + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, array('this' => $oObj)); + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $oAllowedValues, $currentValue, $iInputId, false, $sSuffix, ''); $oWidget->SearchObjectsToSelect($oPage, $sTargetClass); break; @@ -105,8 +105,8 @@ try $sValue = utils::ReadParam('sValue', ''); //$oWizardHelper = WizardHelper::FromJSON($sJson); //$oObj = $oWizardHelper->GetTargetObject(); - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array() /*array('this' => $oObj)*/); - $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $sValue, $iInputId, false, $sSuffix, ''); + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, array() /*array('this' => $oObj)*/); + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $oAllowedValues, $sValue, $iInputId, false, $sSuffix, ''); $oWidget->GetSearchDialog($oPage); break; @@ -119,8 +119,8 @@ try $sJson = utils::ReadParam('json', ''); $oWizardHelper = WizardHelper::FromJSON($sJson); $oObj = $oWizardHelper->GetTargetObject(); - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj)); - $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, $oObj->Get($sAttCode), $iInputId, false, $sSuffix, ''); + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, array('this' => $oObj)); + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $oAllowedValues, $oObj->Get($sAttCode), $iInputId, false, $sSuffix, ''); $oWidget->GetObjectCreationForm($oPage); break; @@ -133,9 +133,9 @@ try $sJson = utils::ReadParam('json', ''); $oWizardHelper = WizardHelper::FromJSON($sJson); $oObj = $oWizardHelper->GetTargetObject(); - $aAllowedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array('this' => $oObj)); + $oAllowedValues = MetaModel::GetAllowedValuesAsObjectSet($sClass, $sAttCode, array('this' => $oObj)); // The iInputId of the autocomplete is the prefix for the form used to create the target object - $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $aAllowedValues, null, $iInputId, false, $sSuffix, $oWizardHelper->GetFormPrefix()); + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', $oAllowedValues, null, $iInputId, false, $sSuffix, $oWizardHelper->GetFormPrefix()); $aResult = $oWidget->DoCreateObject($oPage); echo json_encode($aResult); break; @@ -147,7 +147,7 @@ try $iInputId = utils::ReadParam('iInputId', ''); $iObjectId = utils::ReadParam('iObjectId', ''); $sSuffix = utils::ReadParam('sSuffix', ''); - $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', array(), '', $iInputId, $sSuffix, ''); + $oWidget = new UIExtKeyWidget($sAttCode, $sClass, '', null, '', $iInputId, $sSuffix, ''); $sName = $oWidget->GetObjectName($iObjectId); echo json_encode(array('name' => $sName)); break;