/**
  * 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);
 }
예제 #4
0
 /**
  * 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);
                 }
             }
         }
     }
 }
예제 #5
0
 /**
  * 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;
 }
예제 #7
0
 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;
 }
예제 #8
0
 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;
 }
예제 #11
0
 /**
  * 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;
 }
예제 #12
0
 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);
 }
예제 #13
0
 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);
 }