/** * Helper to complete the renaming of a class * The renaming is made in the datamodel definition, but the name has to be changed in the DB as well * Must be called after DB update, i.e within an implementation of AfterDatabaseCreation() * * @param string $sFrom Original name (already INVALID in the current datamodel) * @param string $sTo New name (valid in the current datamodel) * @return void */ public static function RenameClassInDB($sFrom, $sTo) { if (!MetaModel::IsStandaloneClass($sTo)) { $sRootClass = MetaModel::GetRootClass($sTo); $sTableName = MetaModel::DBGetTable($sRootClass); $sFinalClassCol = MetaModel::DBGetClassField($sRootClass); $sRepair = "UPDATE `{$sTableName}` SET `{$sFinalClassCol}` = '{$sTo}' WHERE `{$sFinalClassCol}` = BINARY '{$sFrom}'"; CMDBSource::Query($sRepair); $iAffectedRows = CMDBSource::AffectedRows(); SetupPage::log_info("Renaming class in DB - final class from '{$sFrom}' to '{$sTo}': {$iAffectedRows} rows affected"); } }
/** * Helper to complete the renaming of a class * The renaming is made in the datamodel definition, but the name has to be changed in the DB as well * Must be called after DB update, i.e within an implementation of AfterDatabaseCreation() * * @param string $sFrom Original name (already INVALID in the current datamodel) * @param string $sTo New name (valid in the current datamodel) * @return void */ public static function RenameClassInDB($sFrom, $sTo) { try { if (!MetaModel::IsStandaloneClass($sTo)) { $sRootClass = MetaModel::GetRootClass($sTo); $sTableName = MetaModel::DBGetTable($sRootClass); $sFinalClassCol = MetaModel::DBGetClassField($sRootClass); $sRepair = "UPDATE `{$sTableName}` SET `{$sFinalClassCol}` = '{$sTo}' WHERE `{$sFinalClassCol}` = BINARY '{$sFrom}'"; CMDBSource::Query($sRepair); $iAffectedRows = CMDBSource::AffectedRows(); SetupPage::log_info("Renaming class in DB - final class from '{$sFrom}' to '{$sTo}': {$iAffectedRows} rows affected"); } } catch (Exception $e) { SetupPage::log_warning("Failed to rename class in DB - final class from '{$sFrom}' to '{$sTo}'. Reason: " . $e->getMessage()); } }
public function GetRootClass($sClass) { return MetaModel::GetRootClass($sClass); }
/** * Check the validity of the expression with regard to the data model * and the query in which it is used * * @param ModelReflection $oModelReflection MetaModel to consider * @throws OqlNormalizeException */ public function Check(ModelReflection $oModelReflection, $sSourceQuery) { $aColumnToClasses = array(); foreach ($this->aQueries as $iQuery => $oQuery) { $oQuery->Check($oModelReflection, $sSourceQuery); $aAliasToClass = array($oQuery->GetClassAlias() => $oQuery->GetClass()); $aJoinSpecs = $oQuery->GetJoins(); if (is_array($aJoinSpecs)) { foreach ($aJoinSpecs as $oJoinSpec) { $aAliasToClass[$oJoinSpec->GetClassAlias()] = $oJoinSpec->GetClass(); } } $aSelectedClasses = $oQuery->GetSelectedClasses(); if ($iQuery != 0) { if (count($aSelectedClasses) < count($aColumnToClasses)) { $oLastClass = end($aSelectedClasses); throw new OqlNormalizeException('Too few selected classes in the subquery', $sSourceQuery, $oLastClass); } if (count($aSelectedClasses) > count($aColumnToClasses)) { $oLastClass = end($aSelectedClasses); throw new OqlNormalizeException('Too many selected classes in the subquery', $sSourceQuery, $oLastClass); } } foreach ($aSelectedClasses as $iColumn => $oClassDetails) { $sAlias = $oClassDetails->GetValue(); $sClass = $aAliasToClass[$sAlias]; $aColumnToClasses[$iColumn][] = array('alias' => $sAlias, 'class' => $sClass, 'class_name' => $oClassDetails); } } foreach ($aColumnToClasses as $iColumn => $aClasses) { foreach ($aClasses as $iQuery => $aData) { if ($iQuery == 0) { // Establish the reference $sRootClass = MetaModel::GetRootClass($aData['class']); } else { if (MetaModel::GetRootClass($aData['class']) != $sRootClass) { $aSubclasses = MetaModel::EnumChildClasses($sRootClass, ENUM_CHILD_CLASSES_ALL); throw new OqlNormalizeException('Incompatible classes: could not find a common ancestor', $sSourceQuery, $aData['class_name'], $aSubclasses); } } } } }
/** * The root class (i.e. highest ancestor in the MeaModel class hierarchy) for the first column on this set * * @return string The root class for the objects in the first column of the set */ public function GetRootClass() { return MetaModel::GetRootClass($this->GetClass()); }
protected function MakeSQLObjectQuery(&$oBuild, $aAttToLoad = null, $aValues = array()) { // Note: query class might be different than the class of the filter // -> this occurs when we are linking our class to an external class (referenced by, or pointing to) $sClass = $this->GetFirstJoinedClass(); $sClassAlias = $this->GetFirstJoinedClassAlias(); $bIsOnQueriedClass = array_key_exists($sClassAlias, $oBuild->GetRootFilter()->GetSelectedClasses()); self::DbgTrace("Entering: " . $this->ToOQL() . ", " . ($bIsOnQueriedClass ? "MAIN" : "SECONDARY")); $sRootClass = MetaModel::GetRootClass($sClass); $sKeyField = MetaModel::DBGetKey($sClass); if ($bIsOnQueriedClass) { // default to the whole list of attributes + the very std id/finalclass $oBuild->m_oQBExpressions->AddSelect($sClassAlias . 'id', new FieldExpression('id', $sClassAlias)); if (is_null($aAttToLoad) || !array_key_exists($sClassAlias, $aAttToLoad)) { $sSelectedClass = $oBuild->GetSelectedClass($sClassAlias); $aAttList = MetaModel::ListAttributeDefs($sSelectedClass); } else { $aAttList = $aAttToLoad[$sClassAlias]; } foreach ($aAttList as $sAttCode => $oAttDef) { if (!$oAttDef->IsScalar()) { continue; } // keep because it can be used for sorting - if (!$oAttDef->LoadInObject()) continue; foreach ($oAttDef->GetSQLExpressions() as $sColId => $sSQLExpr) { $oBuild->m_oQBExpressions->AddSelect($sClassAlias . $sAttCode . $sColId, new FieldExpression($sAttCode . $sColId, $sClassAlias)); } } // Transform the full text condition into additional condition expression $aFullText = $this->GetCriteria_FullText(); if (count($aFullText) > 0) { $aFullTextFields = array(); foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if (!$oAttDef->IsScalar()) { continue; } if ($oAttDef->IsExternalKey()) { continue; } $aFullTextFields[] = new FieldExpression($sAttCode, $sClassAlias); } $oTextFields = new CharConcatWSExpression(' ', $aFullTextFields); foreach ($aFullText as $sFTNeedle) { $oNewCond = new BinaryExpression($oTextFields, 'LIKE', new ScalarExpression("%{$sFTNeedle}%")); $oBuild->m_oQBExpressions->AddCondition($oNewCond); } } } //echo "<p>oQBExpr ".__LINE__.": <pre>\n".print_r($oBuild->m_oQBExpressions, true)."</pre></p>\n"; $aExpectedAtts = array(); // array of (attcode => fieldexpression) //echo "<p>".__LINE__.": GetUnresolvedFields($sClassAlias, ...)</p>\n"; $oBuild->m_oQBExpressions->GetUnresolvedFields($sClassAlias, $aExpectedAtts); // Compute a clear view of required joins (from the current class) // Build the list of external keys: // -> ext keys required by an explicit join // -> ext keys mentionned in a 'pointing to' condition // -> ext keys required for an external field // -> ext keys required for a friendly name // $aExtKeys = array(); // array of sTableClass => array of (sAttCode (keys) => array of (sAttCode (fields)=> oAttDef)) // // Optimization: could be partially computed once for all (cached) ? // if ($bIsOnQueriedClass) { // Get all Ext keys for the queried class (??) foreach (MetaModel::GetKeysList($sClass) as $sKeyAttCode) { $sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode); $aExtKeys[$sKeyTableClass][$sKeyAttCode] = array(); } } // Get all Ext keys used by the filter foreach ($this->GetCriteria_PointingTo() as $sKeyAttCode => $aPointingTo) { if (array_key_exists(TREE_OPERATOR_EQUALS, $aPointingTo)) { $sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode); $aExtKeys[$sKeyTableClass][$sKeyAttCode] = array(); } } $aFNJoinAlias = array(); // array of (subclass => alias) if (array_key_exists('friendlyname', $aExpectedAtts)) { // To optimize: detect a restriction on child classes in the condition expression // e.g. SELECT FunctionalCI WHERE finalclass IN ('Server', 'VirtualMachine') $oNameExpression = self::GetExtendedNameExpression($sClass); $aNameFields = array(); $oNameExpression->GetUnresolvedFields('', $aNameFields); $aTranslateNameFields = array(); foreach ($aNameFields as $sSubClass => $aFields) { foreach ($aFields as $sAttCode => $oField) { $oAttDef = MetaModel::GetAttributeDef($sSubClass, $sAttCode); if ($oAttDef->IsExternalKey()) { $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode); $aExtKeys[$sClassOfAttribute][$sAttCode] = array(); } elseif ($oAttDef->IsExternalField() || $oAttDef instanceof AttributeFriendlyName) { $sKeyAttCode = $oAttDef->GetKeyAttCode(); $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sKeyAttCode); $aExtKeys[$sClassOfAttribute][$sKeyAttCode][$sAttCode] = $oAttDef; } else { $sClassOfAttribute = MetaModel::GetAttributeOrigin($sSubClass, $sAttCode); } if (MetaModel::IsParentClass($sClassOfAttribute, $sClass)) { // The attribute is part of the standard query // $sAliasForAttribute = $sClassAlias; } else { // The attribute will be available from an additional outer join // For each subclass (table) one single join is enough // if (!array_key_exists($sClassOfAttribute, $aFNJoinAlias)) { $sAliasForAttribute = $oBuild->GenerateClassAlias($sClassAlias . '_fn_' . $sClassOfAttribute, $sClassOfAttribute); $aFNJoinAlias[$sClassOfAttribute] = $sAliasForAttribute; } else { $sAliasForAttribute = $aFNJoinAlias[$sClassOfAttribute]; } } $aTranslateNameFields[$sSubClass][$sAttCode] = new FieldExpression($sAttCode, $sAliasForAttribute); } } $oNameExpression = $oNameExpression->Translate($aTranslateNameFields, false); $aTranslateNow = array(); $aTranslateNow[$sClassAlias]['friendlyname'] = $oNameExpression; $oBuild->m_oQBExpressions->Translate($aTranslateNow, false); } // Add the ext fields used in the select (eventually adds an external key) foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if ($oAttDef->IsExternalField() || $oAttDef instanceof AttributeFriendlyName) { if (array_key_exists($sAttCode, $aExpectedAtts)) { $sKeyAttCode = $oAttDef->GetKeyAttCode(); if ($sKeyAttCode != 'id') { // Add the external attribute $sKeyTableClass = MetaModel::GetAttributeOrigin($sClass, $sKeyAttCode); $aExtKeys[$sKeyTableClass][$sKeyAttCode][$sAttCode] = $oAttDef; } } } } // First query built upon on the leaf (ie current) class // self::DbgTrace("Main (=leaf) class, call MakeSQLObjectQuerySingleTable()"); if (MetaModel::HasTable($sClass)) { $oSelectBase = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sClass, $aExtKeys, $aValues); } else { $oSelectBase = null; // As the join will not filter on the expected classes, we have to specify it explicitely $sExpectedClasses = implode("', '", MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL)); $oFinalClassRestriction = Expression::FromOQL("`{$sClassAlias}`.finalclass IN ('{$sExpectedClasses}')"); $oBuild->m_oQBExpressions->AddCondition($oFinalClassRestriction); } // Then we join the queries of the eventual parent classes (compound model) foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) { if (!MetaModel::HasTable($sParentClass)) { continue; } self::DbgTrace("Parent class: {$sParentClass}... let's call MakeSQLObjectQuerySingleTable()"); $oSelectParentTable = $this->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sParentClass, $aExtKeys, $aValues); if (is_null($oSelectBase)) { $oSelectBase = $oSelectParentTable; } else { $oSelectBase->AddInnerJoin($oSelectParentTable, $sKeyField, MetaModel::DBGetKey($sParentClass)); } } // Filter on objects referencing me foreach ($this->GetCriteria_ReferencedBy() as $sForeignClass => $aKeysAndFilters) { foreach ($aKeysAndFilters as $sForeignKeyAttCode => $oForeignFilter) { $oForeignKeyAttDef = MetaModel::GetAttributeDef($sForeignClass, $sForeignKeyAttCode); self::DbgTrace("Referenced by foreign key: {$sForeignKeyAttCode}... let's call MakeSQLObjectQuery()"); //self::DbgTrace($oForeignFilter); //self::DbgTrace($oForeignFilter->ToOQL()); //self::DbgTrace($oSelectForeign); //self::DbgTrace($oSelectForeign->RenderSelect(array())); $sForeignClassAlias = $oForeignFilter->GetFirstJoinedClassAlias(); $oBuild->m_oQBExpressions->PushJoinField(new FieldExpression($sForeignKeyAttCode, $sForeignClassAlias)); if ($oForeignKeyAttDef instanceof AttributeObjectKey) { $sClassAttCode = $oForeignKeyAttDef->Get('class_attcode'); // Add the condition: `$sForeignClassAlias`.$sClassAttCode IN (subclasses of $sClass') $oClassListExpr = ListExpression::FromScalars(MetaModel::EnumChildClasses($sClass, ENUM_CHILD_CLASSES_ALL)); $oClassExpr = new FieldExpression($sClassAttCode, $sForeignClassAlias); $oClassRestriction = new BinaryExpression($oClassExpr, 'IN', $oClassListExpr); $oBuild->m_oQBExpressions->AddCondition($oClassRestriction); } $oSelectForeign = $oForeignFilter->MakeSQLObjectQuery($oBuild, $aAttToLoad); $oJoinExpr = $oBuild->m_oQBExpressions->PopJoinField(); $sForeignKeyTable = $oJoinExpr->GetParent(); $sForeignKeyColumn = $oJoinExpr->GetName(); $oSelectBase->AddInnerJoin($oSelectForeign, $sKeyField, $sForeignKeyColumn, $sForeignKeyTable); } } // Additional JOINS for Friendly names // foreach ($aFNJoinAlias as $sSubClass => $sSubClassAlias) { $oSubClassFilter = new DBObjectSearch($sSubClass, $sSubClassAlias); $oSelectFN = $oSubClassFilter->MakeSQLObjectQuerySingleTable($oBuild, $aAttToLoad, $sSubClass, $aExtKeys, array()); $oSelectBase->AddLeftJoin($oSelectFN, $sKeyField, MetaModel::DBGetKey($sSubClass)); } // That's all... cross fingers and we'll get some working query //MyHelpers::var_dump_html($oSelectBase, true); //MyHelpers::var_dump_html($oSelectBase->RenderSelect(), true); if (self::$m_bDebugQuery) { $oSelectBase->DisplayHtml(); } return $oSelectBase; }
public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array()) { foreach (MetaModel::EnumRelationQueries(get_class($this), $sRelCode) as $sDummy => $aQueryInfo) { MetaModel::DbgTrace("object=" . $this->GetKey() . ", depth={$iMaxDepth}, rel=" . $aQueryInfo["sQuery"]); $sQuery = $aQueryInfo["sQuery"]; $bPropagate = $aQueryInfo["bPropagate"]; $iDistance = $aQueryInfo["iDistance"]; $iDepth = $bPropagate ? $iMaxDepth - 1 : 0; $oFlt = DBObjectSearch::FromOQL($sQuery); $oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgsForQuery()); 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 $aResults; }
public static function GetNextKey($sClass) { $sRootClass = MetaModel::GetRootClass($sClass); $sRootTable = MetaModel::DBGetTable($sRootClass); $iNextKey = CMDBSource::GetNextInsertId($sRootTable); return $iNextKey; }
protected function RecordObjDeletion($objkey) { $sRootClass = MetaModel::GetRootClass(get_class($this)); // Delete any existing change tracking about the current object $oFilter = new DBObjectSearch('CMDBChangeOp'); $oFilter->AddCondition('objclass', get_class($this), '='); $oFilter->AddCondition('objkey', $objkey, '='); MetaModel::PurgeData($oFilter); parent::RecordObjDeletion($objkey); $oMyChangeOp = MetaModel::NewObject("CMDBChangeOpDelete"); $oMyChangeOp->Set("objclass", MetaModel::GetRootClass(get_class($this))); $oMyChangeOp->Set("objkey", $objkey); $oMyChangeOp->Set("fclass", get_class($this)); $oMyChangeOp->Set("fname", substr($this->GetRawName(), 0, 255)); // Protect against very long friendly names $iId = $oMyChangeOp->DBInsertNoReload(); }
protected function LoadValues($aArgs) { $this->m_aValues = array(); if (!array_key_exists('this', $aArgs)) { throw new CoreException("Missing 'this' in arguments", array('args' => $aArgs)); } $oTarget = $aArgs['this->object()']; // 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; } } // #@# or AddObjectArray($aObjects) ? $oSetToCreate = DBObjectSet::FromArray($this->m_sTargetLinkClass, $aLinksToCreate); $this->m_aValues[$oObject->GetKey()] = $oObject->GetName(); } return true; }
/** * Will be deprecated soon - use GetRelatedObjectsDown/Up instead to take redundancy into account */ public function GetRelatedObjects($sRelCode, $iMaxDepth = 99, &$aResults = array()) { // Temporary patch: until the impact analysis GUI gets rewritten, // let's consider that "depends on" is equivalent to "impacts/up" // The current patch has been implemented in DBObject and MetaModel $sHackedRelCode = $sRelCode; $bDown = true; if ($sRelCode == 'depends on') { $sHackedRelCode = 'impacts'; $bDown = false; } foreach (MetaModel::EnumRelationQueries(get_class($this), $sHackedRelCode, $bDown) as $sDummy => $aQueryInfo) { $sQuery = $bDown ? $aQueryInfo['sQueryDown'] : $aQueryInfo['sQueryUp']; //$bPropagate = $aQueryInfo["bPropagate"]; //$iDepth = $bPropagate ? $iMaxDepth - 1 : 0; $iDepth = $iMaxDepth - 1; // Note: the loop over the result set has been written in an unusual way for error reporting purposes // In the case of a wrong query parameter name, the error occurs on the first call to Fetch, // thus we need to have this first call into the try/catch, but // we do NOT want to nest the try/catch for the error message to be clear try { $oFlt = DBObjectSearch::FromOQL($sQuery); $oObjSet = new DBObjectSet($oFlt, array(), $this->ToArgsForQuery()); $oObj = $oObjSet->Fetch(); } catch (Exception $e) { $sClassOfDefinition = $aQueryInfo['_legacy_'] ? get_class($this) . '(or a parent)::GetRelationQueries()' : $aQueryInfo['sDefinedInClass']; throw new Exception("Wrong query for the relation {$sRelCode}/{$sClassOfDefinition}/{$aQueryInfo['sNeighbour']}: " . $e->getMessage()); } if ($oObj) { do { $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); } } while ($oObj = $oObjSet->Fetch()); } } return $aResults; }
public function UpdateImpactedItems() { $oContactsSet = $this->Get('contacts_list'); $oCIsSet = $this->Get('functionalcis_list'); $aCIsToImpactCode = array(); $aSources = array(); $aExcluded = array(); $oCIsSet->Rewind(); while ($oLink = $oCIsSet->Fetch()) { $iKey = $oLink->Get('functionalci_id'); $aCIsToImpactCode[$iKey] = $oLink->Get('impact_code'); if ($oLink->Get('impact_code') == 'manual') { $oObj = MetaModel::GetObject('FunctionalCI', $iKey); $aSources[$iKey] = $oObj; } else { if ($oLink->Get('impact_code') == 'not_impacted') { $oObj = MetaModel::GetObject('FunctionalCI', $iKey); $aExcluded[$iKey] = $oObj; } } } $aContactsToRoleCode = array(); $oContactsSet->Rewind(); while ($oLink = $oContactsSet->Fetch()) { $iKey = $oLink->Get('contact_id'); $aContactsToRoleCode[$iKey] = $oLink->Get('role_code'); if ($oLink->Get('role_code') == 'do_not_notify') { $oObj = MetaModel::GetObject('Contact', $iKey); $aExcluded[$iKey] = $oObj; } } $oNewCIsSet = DBObjectSet::FromScratch('lnkFunctionalCIToTicket'); foreach ($aCIsToImpactCode as $iKey => $sImpactCode) { if ($sImpactCode != 'computed') { $oNewLink = new lnkFunctionalCIToTicket(); $oNewLink->Set('functionalci_id', $iKey); $oNewLink->Set('impact_code', $sImpactCode); $oNewCIsSet->AddObject($oNewLink); } } $oNewContactsSet = DBObjectSet::FromScratch('lnkContactToTicket'); foreach ($aContactsToRoleCode as $iKey => $sImpactCode) { if ($sImpactCode != 'computed') { $oNewLink = new lnkContactToTicket(); $oNewLink->Set('contact_id', $iKey); $oNewLink->Set('role_code', $sImpactCode); $oNewContactsSet->AddObject($oNewLink); } } $oContactsSet = DBObjectSet::FromScratch('lnkContactToTicket'); $oGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true, $aExcluded); $oIterator = new RelationTypeIterator($oGraph, 'Node'); foreach ($oIterator as $oNode) { if ($oNode instanceof RelationObjectNode && $oNode->GetProperty('is_reached') && !$oNode->GetProperty('source')) { $oObj = $oNode->GetProperty('object'); $iKey = $oObj->GetKey(); $sRootClass = MetaModel::GetRootClass(get_class($oObj)); switch ($sRootClass) { case 'FunctionalCI': // Only link FunctionalCIs which are not already linked to the ticket if (!array_key_exists($iKey, $aCIsToImpactCode) || $aCIsToImpactCode[$iKey] != 'not_impacted') { $oNewLink = new lnkFunctionalCIToTicket(); $oNewLink->Set('functionalci_id', $iKey); $oNewLink->Set('impact_code', 'computed'); $oNewCIsSet->AddObject($oNewLink); } break; case 'Contact': // Only link Contacts which are not already linked to the ticket if (!array_key_exists($iKey, $aContactsToRoleCode) || $aCIsToImpactCode[$iKey] != 'do_not_notify') { $oNewLink = new lnkContactToTicket(); $oNewLink->Set('contact_id', $iKey); $oNewLink->Set('role_code', 'computed'); $oNewContactsSet->AddObject($oNewLink); } break; } } } $this->Set('functionalcis_list', $oNewCIsSet); $this->Set('contacts_list', $oNewContactsSet); }
public function UpdateImpactedItems() { require_once APPROOT . 'core/displayablegraph.class.inc.php'; $oContactsSet = $this->Get('contacts_list'); $oCIsSet = $this->Get('functionalcis_list'); $aCIsToImpactCode = array(); $aSources = array(); $aExcluded = array(); $oCIsSet->Rewind(); while ($oLink = $oCIsSet->Fetch()) { $iKey = $oLink->Get('functionalci_id'); $aCIsToImpactCode[$iKey] = $oLink->Get('impact_code'); if ($oLink->Get('impact_code') == 'manual') { $oObj = MetaModel::GetObject('FunctionalCI', $iKey); $aSources[$iKey] = $oObj; } else { if ($oLink->Get('impact_code') == 'not_impacted') { $oObj = MetaModel::GetObject('FunctionalCI', $iKey); $aExcluded[$iKey] = $oObj; } } } $aContactsToRoleCode = array(); $oContactsSet->Rewind(); while ($oLink = $oContactsSet->Fetch()) { $iKey = $oLink->Get('contact_id'); $aContactsToRoleCode[$iKey] = $oLink->Get('role_code'); if ($oLink->Get('role_code') == 'do_not_notify') { $oObj = MetaModel::GetObject('Contact', $iKey); $aExcluded[$iKey] = $oObj; } } $oNewCIsSet = DBObjectSet::FromScratch('lnkFunctionalCIToTicket'); foreach ($aCIsToImpactCode as $iKey => $sImpactCode) { if ($sImpactCode != 'computed') { $oNewLink = new lnkFunctionalCIToTicket(); $oNewLink->Set('functionalci_id', $iKey); $oNewLink->Set('impact_code', $sImpactCode); $oNewCIsSet->AddObject($oNewLink); } } $oNewContactsSet = DBObjectSet::FromScratch('lnkContactToTicket'); foreach ($aContactsToRoleCode as $iKey => $sImpactCode) { if ($sImpactCode != 'computed') { $oNewLink = new lnkContactToTicket(); $oNewLink->Set('contact_id', $iKey); $oNewLink->Set('role_code', $sImpactCode); $oNewContactsSet->AddObject($oNewLink); } } $oContactsSet = DBObjectSet::FromScratch('lnkContactToTicket'); $sContextKey = 'itop-tickets/relation_context/' . get_class($this) . '/impacts/down'; $aContextDefs = DisplayableGraph::GetContextDefinitions($sContextKey, true, array('this' => $this)); $aDefaultContexts = array(); foreach ($aContextDefs as $sKey => $aDefinition) { // Add the default context queries to the computation if (array_key_exists('default', $aDefinition) && $aDefinition['default'] == 'yes') { $aDefaultContexts[] = $aDefinition['oql']; } } // Merge the directly impacted items with the "new" ones added by the "context" queries $aGraphObjects = array(); $oRawGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true, $aExcluded); $oIterator = new RelationTypeIterator($oRawGraph, 'Node'); foreach ($oIterator as $oNode) { // Any object node reached AND different from a source will do if ($oNode instanceof RelationObjectNode && $oNode->GetProperty('is_reached') && !$oNode->GetProperty('source')) { $oObj = $oNode->GetProperty('object'); $iKey = $oObj->GetKey(); $sRootClass = MetaModel::GetRootClass(get_class($oObj)); $aGraphObjects[get_class($oObj) . '::' . $iKey] = $oNode->GetProperty('object'); } } if (count($aDefaultContexts) > 0) { $oAnnotatedGraph = MetaModel::GetRelatedObjectsDown('impacts', $aSources, 10, true, $aExcluded, $aDefaultContexts); $oIterator = new RelationTypeIterator($oAnnotatedGraph, 'Node'); foreach ($oIterator as $oNode) { // Only pick the nodes which are NOT impacted by a context root cause, and merge them in the list if ($oNode instanceof RelationObjectNode && $oNode->GetProperty('is_reached') && !$oNode->GetProperty('source') && $oNode->GetProperty('context_root_causes', null) == null) { $oObj = $oNode->GetProperty('object'); $iKey = $oObj->GetKey(); $sRootClass = MetaModel::GetRootClass(get_class($oObj)); $aGraphObjects[get_class($oObj) . '::' . $iKey] = $oNode->GetProperty('object'); } } } foreach ($aGraphObjects as $oObj) { $iKey = $oObj->GetKey(); $sRootClass = MetaModel::GetRootClass(get_class($oObj)); switch ($sRootClass) { case 'FunctionalCI': // Only link FunctionalCIs which are not already linked to the ticket if (!array_key_exists($iKey, $aCIsToImpactCode) || $aCIsToImpactCode[$iKey] != 'not_impacted') { $oNewLink = new lnkFunctionalCIToTicket(); $oNewLink->Set('functionalci_id', $iKey); $oNewLink->Set('impact_code', 'computed'); $oNewCIsSet->AddObject($oNewLink); } break; case 'Contact': // Only link Contacts which are not already linked to the ticket if (!array_key_exists($iKey, $aContactsToRoleCode) || $aCIsToImpactCode[$iKey] != 'do_not_notify') { $oNewLink = new lnkContactToTicket(); $oNewLink->Set('contact_id', $iKey); $oNewLink->Set('role_code', 'computed'); $oNewContactsSet->AddObject($oNewLink); } break; } } $this->Set('functionalcis_list', $oNewCIsSet); $this->Set('contacts_list', $oNewContactsSet); }