From e2524d28d700a6ffb9adaf789d4827b7547c40a9 Mon Sep 17 00:00:00 2001 From: Romain Quetiez Date: Tue, 9 Mar 2010 14:09:51 +0000 Subject: [PATCH] Related objects: - moved to OQL - added capacity to set a default value based on the related objects (during the creation wizard) SVN:trunk[314] --- application/uilinkswizard.class.inc.php | 2 +- application/uiwizard.class.inc.php | 16 ++++----- core/attributedef.class.inc.php | 20 +++-------- core/dbobject.class.php | 46 ++++++------------------- core/dbobjectsearch.class.php | 2 +- core/dbobjectset.class.php | 21 ++++++++++- core/valuesetdef.class.inc.php | 37 +++++++++++++++++--- 7 files changed, 78 insertions(+), 66 deletions(-) diff --git a/application/uilinkswizard.class.inc.php b/application/uilinkswizard.class.inc.php index ede866c45..70e89d226 100644 --- a/application/uilinkswizard.class.inc.php +++ b/application/uilinkswizard.class.inc.php @@ -285,7 +285,7 @@ class UILinksWizard foreach($this->m_aEditableFields as $sFieldCode) { $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sFieldCode); - $aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sClass, $sFieldCode, $oAttDef, '' /* TO DO/ call GetDefaultValue */, '' /* DisplayValue */, '' /* id */, $sNameSuffix); + $aRow[$sFieldCode] = cmdbAbstractObject::GetFormElementForField($oP, $this->m_sClass, $sFieldCode, $oAttDef, '' /* TO DO/ call GetDefaultValue($oObject->ToArgs()) */, '' /* DisplayValue */, '' /* id */, $sNameSuffix); } } foreach(MetaModel::GetZListItems($this->m_sLinkedClass, 'list') as $sFieldCode) diff --git a/application/uiwizard.class.inc.php b/application/uiwizard.class.inc.php index f2819ff47..c1b5c0e0a 100644 --- a/application/uiwizard.class.inc.php +++ b/application/uiwizard.class.inc.php @@ -59,7 +59,7 @@ class UIWizard } $sFieldFlag = (($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE)) || (!$oAttDef->IsNullAllowed()) )? ' *' : ''; - $oDefaultValuesSet = $oAttDef->GetDefaultValue(); // @@@ TO DO: get the object's current value if the object exists + $oDefaultValuesSet = $oAttDef->GetDefaultValue(/* $oObject->ToArgs() */); // @@@ TO DO: get the object's current value if the object exists $sHTMLValue = cmdbAbstractObject::GetFormElementForField($this->m_oPage, $this->m_sClass, $sAttCode, $oAttDef, $oDefaultValuesSet, '', "att_$iMaxInputId", '', $iOptions, $aArgs); $aFieldsMap[$iMaxInputId] = $sAttCode; $aDetails[] = array('label' => $oAttDef->GetLabel().$sFieldFlag, 'value' => "
$sHTMLValue
"); @@ -165,7 +165,7 @@ $sJSHandlerCode $aFields = array(); foreach($aStates[$this->m_sTargetState]['attribute_list'] as $sAttCode => $iOptions) { - if ( (isset($aMandatoryAttributes[$sAttCode])) && + if ( (isset($aMandatoryAttributes[$sAttCode])) && ($aMandatoryAttributes[$sAttCode] & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) ) { $aMandatoryAttributes[$sAttCode] |= $iOptions; @@ -176,16 +176,16 @@ $sJSHandlerCode } } } - - // Check all the fields that *must* be included in the wizard - // i.e. all mandatory, must-change or must-prompt fields that are - // not also read-only or hidden. - // Some fields may be required (null not allowed) from the database + + // Check all the fields that *must* be included in the wizard + // i.e. all mandatory, must-change or must-prompt fields that are + // not also read-only or hidden. + // Some fields may be required (null not allowed) from the database // perspective, but hidden or read-only from the user interface perspective $aFields = array(); foreach($aMandatoryAttributes as $sAttCode => $iOptions) { - if ( ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) && + if ( ($iOptions & (OPT_ATT_MANDATORY | OPT_ATT_MUSTCHANGE | OPT_ATT_MUSTPROMPT)) && !($iOptions & (OPT_ATT_READONLY | OPT_ATT_HIDDEN)) ) { $oAttDef = MetaModel::GetAttributeDef($this->m_sClass, $sAttCode); diff --git a/core/attributedef.class.inc.php b/core/attributedef.class.inc.php index b9728acae..882bf531f 100644 --- a/core/attributedef.class.inc.php +++ b/core/attributedef.class.inc.php @@ -241,28 +241,18 @@ class AttributeLinkedSet extends AttributeDefinition // if (($this->IsParam('default_value')) && array_key_exists('this', $aArgs)) { - $oSet = $this->Get('default_value'); - return $oSet->GetValues($aArgs); +echo "### this est la
\n"; + $aValues = $this->Get('default_value')->GetValues($aArgs); + $oSet = DBObjectSet::FromArray($this->Get('linked_class'), $aValues); + return $oSet; } else { +echo "### this manque a l'appel
\n"; return DBObjectSet::FromScratch($this->Get('linked_class')); } } - public function GetSupportedRelations() - { - if (array_key_exists('supported_relations', $this->m_aParams)) - { - $aSupportedRelations = $this->Get('supported_relations'); - return $aSupportedRelations; - } - else - { - return array(); - } - } - public function GetLinkedClass() {return $this->Get('linked_class');} public function GetExtKeyToMe() {return $this->Get('ext_key_to_me');} diff --git a/core/dbobject.class.php b/core/dbobject.class.php index f0ddffe8d..07c498b44 100644 --- a/core/dbobject.class.php +++ b/core/dbobject.class.php @@ -229,7 +229,7 @@ abstract class DBObject } public function Set($sAttCode, $value) - { + { if ($sAttCode == 'finalclass') { // Ignore it - this attribute is set upon object creation and that's it @@ -665,6 +665,11 @@ abstract class DBObject } return $this->m_iKey; } + + // To be optionaly overloaded + public function OnInsert() + { + } // Insert of record for the new object into the database // Returns the key of the newly created object @@ -680,6 +685,7 @@ abstract class DBObject // Ensure the update of the values (we are accessing the data directly) $this->ComputeFields(); + $this->OnInsert(); if ($this->m_iKey < 0) { @@ -878,7 +884,7 @@ abstract class DBObject } // Make standard context arguments - public function ToArgs($sArgName) + public function ToArgs($sArgName = 'this') { $aScalarArgs = array(); $aScalarArgs[$sArgName] = $this->GetKey(); @@ -904,38 +910,6 @@ abstract class DBObject public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array()) { - foreach (MetaModel::GetLinkedSets($sClass) as $sAttCode => $oAttDef) - { - $aSupportedRelations = $oAttDef->GetSupportedRelations(); - if (!array_key_exists($sRelCode, $aSupportedRelations)) continue; //skip - - $bPropagate = true; // #@# Todo: discuss that setting - $iDepth = $bPropagate ? $iMaxDepth - 1 : 0; - - $oNeighbors = $this->Get($sAttCode); - while ($oObj = $oObjSet->Fetch()) - { - $sRootClass = MetaModel::GetRootClass(get_class($oObj)); - $sObjKey = $oObj->GetKey(); - if (array_key_exists($sRootClass, $aResults)) - { - if (array_key_exists($sObjKey, $aResults[$sRootClass])) - { - continue; // already visited, skip - } - } - - $aResults[$sRootClass][$sObjKey] = $oObj; - if ($iDepth > 0) - { - $oObj->GetRelatedObjects($sRelCode, $iDepth, $aResults); - } - } - } - - return; - - // #@# todo : Discuss the Relations and the way they are defined (do we deprecate the queries ? what are the properties -e.g. depth- and where do we set them ?) foreach (MetaModel::EnumRelationQueries(get_class($this), $sRelCode) as $sDummy => $aQueryInfo) { MetaModel::DbgTrace("object=".$this->GetKey().", depth=$iMaxDepth, rel=".$aQueryInfo["sQuery"]); @@ -945,8 +919,8 @@ abstract class DBObject $iDepth = $bPropagate ? $iMaxDepth - 1 : 0; - $oFlt = DBObjectSearch::FromSibusQL($sQuery, array(), $this); - $oObjSet = new DBObjectSet($oFlt); + $oFlt = DBObjectSearch::FromOQL($sQuery); + $oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgs()); while ($oObj = $oObjSet->Fetch()) { $sRootClass = MetaModel::GetRootClass(get_class($oObj)); diff --git a/core/dbobjectsearch.class.php b/core/dbobjectsearch.class.php index 71dda9508..bec0d57ff 100644 --- a/core/dbobjectsearch.class.php +++ b/core/dbobjectsearch.class.php @@ -933,7 +933,7 @@ class DBObjectSearch if (preg_match('@^\\s*SELECT@', $sQuery)) { - return self::FromOQL($sQuery, $aParams, $oObject); + return self::FromOQL($sQuery); } $iSepPos = strpos($sQuery, ":"); diff --git a/core/dbobjectset.class.php b/core/dbobjectset.class.php index 6655b38bc..1fcea5545 100644 --- a/core/dbobjectset.class.php +++ b/core/dbobjectset.class.php @@ -81,6 +81,22 @@ class DBObjectSet return $oRetSet; } + static public function FromLinkSet($oObject, $sLinkSetAttCode, $sExtKeyToRemote) + { + $oLinkAttCode = MetaModel::GetAttributeDef(get_class($oObject), $sLinkSetAttCode); + $oExtKeyAttDef = MetaModel::GetAttributeDef($oLinkAttCode->GetLinkedClass(), $sExtKeyToRemote); + $sTargetClass = $oExtKeyAttDef->GetTargetClass(); + + $oLinkSet = $oObject->Get($sLinkSetAttCode); + $aTargets = array(); + while ($oLink = $oLinkSet->Fetch()) + { + $aTargets[] = MetaModel::GetObject($sTargetClass, $oLink->Get($sExtKeyToRemote)); + } + + return self::FromArray($sTargetClass, $aTargets); + } + public function ToArray($bWithId = true) { $aRet = array(); @@ -263,11 +279,14 @@ class DBObjectSet public function GetRelatedObjects($sRelCode, $iMaxDepth = 99) { + $aRelatedObjs = array(); + $aVisited = array(); // optimization for consecutive calls of MetaModel::GetRelatedObjects $this->Seek(0); while ($oObject = $this->Fetch()) { - $aRelatedObjs = $oObject->GetRelatedObjects($sRelCode, $iMaxDepth, $aVisited); + // #@# todo - actually merge ! + $aRelatedObjs = array_merge_recursive($aRelatedObjs, $oObject->GetRelatedObjects($sRelCode, $iMaxDepth, $aVisited)); } return $aRelatedObjs; } diff --git a/core/valuesetdef.class.inc.php b/core/valuesetdef.class.inc.php index 1d9e315c7..78667e6fa 100644 --- a/core/valuesetdef.class.inc.php +++ b/core/valuesetdef.class.inc.php @@ -126,16 +126,25 @@ class ValueSetObjects extends ValueSetDefinition * @since 1.0 * @version $itopversion$ */ -class ValueSetRelatedObjects extends ValueSetDefinition +class ValueSetRelatedObjectsFromLinkSet extends ValueSetDefinition { + protected $m_sLinkSetAttCode; + protected $m_sExtKeyToRemote; protected $m_sRelationCode; protected $m_iMaxDepth; + protected $m_sTargetClass; + protected $m_sTargetExtKey; // protected $m_aOrderBy; - public function __construct($sRelationCode, $iMaxDepth = 99) + public function __construct($sLinkSetAttCode, $sExtKeyToRemote, $sRelationCode, $iMaxDepth, $sTargetClass, $sTargetLinkClass, $sTargetExtKey) { + $this->m_sLinkSetAttCode = $sLinkSetAttCode; + $this->m_sExtKeyToRemote = $sExtKeyToRemote; $this->m_sRelationCode = $sRelationCode; $this->m_iMaxDepth = $iMaxDepth; + $this->m_sTargetClass = $sTargetClass; + $this->m_sTargetLinkClass = $sTargetLinkClass; + $this->m_sTargetExtKey = $sTargetExtKey; // $this->m_aOrderBy = $aOrderBy; } @@ -150,11 +159,31 @@ class ValueSetRelatedObjects extends ValueSetDefinition $oTarget = $aArgs['this->object()']; - $oTargetNeighbors = $oTarget->GetRelatedObjects($this->m_sRelationCode, $this->m_iMaxDepth); - while ($oObject = $oTargetNeighbors->Fetch()) + // Nodes from which we will start the search for neighbourhood + $oNodes = DBObjectSet::FromLinkSet($oTarget, $this->m_sLinkSetAttCode, $this->m_sExtKeyToRemote); + + // Neighbours, whatever their class + $aRelated = $oNodes->GetRelatedObjects($this->m_sRelationCode, $this->m_iMaxDepth); + + $sRootClass = MetaModel::GetRootClass($this->m_sTargetClass); + if (array_key_exists($sRootClass, $aRelated)) { + $aLinksToCreate = array(); + foreach($aRelated[$sRootClass] as $iKey => $oObject) + { + if (MetaModel::IsParentClass($this->m_sTargetClass, get_class($oObject))) + { + $oNewLink = MetaModel::NewObject($this->m_sTargetLinkClass); + $oNewLink->Set($this->m_sTargetExtKey, $iKey); + //$oNewLink->Set('role', 'concerned by an impacted CI'); + + $aLinksToCreate[] = $oNewLink; + } + } + $oSetToCreate = DBObjectSet::FromArray($this->m_sTargetLinkClass, $aLinksToCreate); $this->m_aValues[$oObject->GetKey()] = $oObject->GetAsHTML($oObject->GetName()); } + return true; }