public function GetDefaultValue($aArgs = array())
 {
     // Note: so far, this feature is a prototype,
     //       later, the argument 'this' should always be present in the arguments
     //
     if ($this->IsParam('default_value') && array_key_exists('this', $aArgs)) {
         $aValues = $this->Get('default_value')->GetValues($aArgs);
         $oSet = DBObjectSet::FromArray($this->Get('linked_class'), $aValues);
         return $oSet;
     } else {
         return DBObjectSet::FromScratch($this->Get('linked_class'));
     }
 }
 /**
  * Updates the object from a flat array of values
  * @param string $aValues array of attcode => scalar or array (N-N links)
  * @return void
  */
 public function UpdateObjectFromArray($aValues)
 {
     foreach ($aValues as $sAttCode => $value) {
         $oAttDef = MetaModel::GetAttributeDef(get_class($this), $sAttCode);
         if ($oAttDef->IsLinkSet() && $oAttDef->IsIndirect()) {
             $aLinks = $value;
             $sLinkedClass = $oAttDef->GetLinkedClass();
             $sExtKeyToRemote = $oAttDef->GetExtKeyToRemote();
             $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
             $oLinkedSet = DBObjectSet::FromScratch($sLinkedClass);
             if (is_array($aLinks)) {
                 foreach ($aLinks as $id => $aData) {
                     if (is_numeric($id)) {
                         if ($id < 0) {
                             // New link to be created, the opposite of the id (-$id) is the ID of the remote object
                             $oLink = MetaModel::NewObject($sLinkedClass);
                             $oLink->Set($sExtKeyToRemote, -$id);
                             $oLink->Set($sExtKeyToMe, $this->GetKey());
                         } else {
                             // Existing link, potentially to be updated...
                             $oLink = MetaModel::GetObject($sLinkedClass, $id);
                         }
                         // Now populate the attributes
                         foreach ($aData as $sName => $value) {
                             if (MetaModel::IsValidAttCode($sLinkedClass, $sName)) {
                                 $oLinkAttDef = MetaModel::GetAttributeDef($sLinkedClass, $sName);
                                 if ($oLinkAttDef->IsWritable()) {
                                     $oLink->Set($sName, $value);
                                 }
                             }
                         }
                         $oLinkedSet->AddObject($oLink);
                     }
                 }
             }
             $this->Set($sAttCode, $oLinkedSet);
         } elseif ($oAttDef->GetEditClass() == 'Document') {
             // There should be an uploaded file with the named attr_<attCode>
             $oDocument = $value['fcontents'];
             if (!$oDocument->IsEmpty()) {
                 // A new file has been uploaded
                 $this->Set($sAttCode, $oDocument);
             }
         } elseif ($oAttDef->GetEditClass() == 'One Way Password') {
             // Check if the password was typed/changed
             $aPwdData = $value;
             if (!is_null($aPwdData) && $aPwdData['changed']) {
                 // The password has been changed or set
                 $this->Set($sAttCode, $aPwdData['value']);
             }
         } elseif ($oAttDef->GetEditClass() == 'Duration') {
             $aDurationData = $value;
             if (!is_array($aDurationData)) {
                 continue;
             }
             $iValue = ((24 * $aDurationData['d'] + $aDurationData['h']) * 60 + $aDurationData['m']) * 60 + $aDurationData['s'];
             $this->Set($sAttCode, $iValue);
             $previousValue = $this->Get($sAttCode);
             if ($previousValue !== $iValue) {
                 $this->Set($sAttCode, $iValue);
             }
         } else {
             if ($oAttDef->GetEditClass() == 'LinkedSet' && !$oAttDef->IsIndirect() && ($oAttDef->GetEditMode() == LINKSET_EDITMODE_INPLACE || $oAttDef->GetEditMode() == LINKSET_EDITMODE_ADDREMOVE)) {
                 $oLinkset = $this->Get($sAttCode);
                 $sLinkedClass = $oLinkset->GetClass();
                 $aObjSet = array();
                 $oLinkset->Rewind();
                 $bModified = false;
                 while ($oLink = $oLinkset->Fetch()) {
                     if (in_array($oLink->GetKey(), $value['to_be_deleted'])) {
                         // The link is to be deleted, don't copy it in the array
                         $bModified = true;
                     } else {
                         if (!array_key_exists('to_be_removed', $value) || !in_array($oLink->GetKey(), $value['to_be_removed'])) {
                             $aObjSet[] = $oLink;
                         }
                     }
                 }
                 if (array_key_exists('to_be_created', $value) && count($value['to_be_created']) > 0) {
                     // Now handle the links to be created
                     foreach ($value['to_be_created'] as $aData) {
                         $sSubClass = $aData['class'];
                         if ($sLinkedClass == $sSubClass || is_subclass_of($sSubClass, $sLinkedClass)) {
                             $aObjData = $aData['data'];
                             $oLink = new $sSubClass();
                             $oLink->UpdateObjectFromArray($aObjData);
                             $aObjSet[] = $oLink;
                             $bModified = true;
                         }
                     }
                 }
                 if (array_key_exists('to_be_added', $value) && count($value['to_be_added']) > 0) {
                     // Now handle the links to be added by making the remote object point to self
                     foreach ($value['to_be_added'] as $iObjKey) {
                         $oLink = MetaModel::GetObject($sLinkedClass, $iObjKey, false);
                         if ($oLink) {
                             $aObjSet[] = $oLink;
                             $bModified = true;
                         }
                     }
                 }
                 if (array_key_exists('to_be_removed', $value) && count($value['to_be_removed']) > 0) {
                     // Now handle the links to be removed by making the remote object point to nothing
                     // Keep them in the set (modified), DBWriteLinks will handle them
                     foreach ($value['to_be_removed'] as $iObjKey) {
                         $oLink = MetaModel::GetObject($sLinkedClass, $iObjKey, false);
                         if ($oLink) {
                             $sExtKeyToMe = $oAttDef->GetExtKeyToMe();
                             $oLink->Set($sExtKeyToMe, null);
                             $aObjSet[] = $oLink;
                             $bModified = true;
                         }
                     }
                 }
                 if ($bModified) {
                     $oNewSet = DBObjectSet::FromArray($oLinkset->GetClass(), $aObjSet);
                     $this->Set($sAttCode, $oNewSet);
                 }
             } else {
                 if (!is_null($value)) {
                     $aAttributes[$sAttCode] = trim($value);
                     $previousValue = $this->Get($sAttCode);
                     if ($previousValue !== $aAttributes[$sAttCode]) {
                         $this->Set($sAttCode, $aAttributes[$sAttCode]);
                     }
                 }
             }
         }
     }
 }
Example #3
0
 /**
  * Build a new set (in memory) made of objects of the given set which are NOT present in the current set
  * 
  * Limitations:
  * The objects inside the set must be written in the database since the comparison is based on their identifiers
  * Sets with several objects per row are NOT supported
  * 
  * @param DBObjectSet $oObjectSet
  * @throws CoreException
  * 
  * @return DBObjectSet The "delta" set.
  */
 public function CreateDelta(DBObjectSet $oObjectSet)
 {
     if ($this->GetRootClass() != $oObjectSet->GetRootClass()) {
         throw new CoreException("Could not 'delta' two objects sets if they don't have the same root class");
     }
     if (!$this->m_bLoaded) {
         $this->Load();
     }
     $aId2Row = array();
     $iCurrPos = $this->m_iCurrRow;
     // Save the cursor
     $idx = 0;
     while ($oObj = $this->Fetch()) {
         $aId2Row[$oObj->GetKey()] = $idx;
         $idx++;
     }
     $oNewSet = DBObjectSet::FromScratch($this->GetClass());
     $oObjectSet->Seek(0);
     while ($oObject = $oObjectSet->Fetch()) {
         if (!array_key_exists($oObject->GetKey(), $aId2Row)) {
             $oNewSet->AddObject($oObject);
         }
     }
     $this->Seek($iCurrPos);
     // Restore the cursor
     return $oNewSet;
 }
 protected static function SetProfilesFromCAS($oUser, $aGroups)
 {
     if (!MetaModel::IsValidClass('URP_Profiles')) {
         phpCAS::log("URP_Profiles is not a valid class. Automatic creation of Users is not supported in this context, sorry.");
         return false;
     }
     // read all the existing profiles
     $oProfilesSearch = new DBObjectSearch('URP_Profiles');
     $oProfilesSet = new DBObjectSet($oProfilesSearch);
     $aAllProfiles = array();
     while ($oProfile = $oProfilesSet->Fetch()) {
         $aAllProfiles[strtolower($oProfile->GetName())] = $oProfile->GetKey();
     }
     // Translate the CAS/LDAP group names into iTop profile names
     $aProfiles = array();
     $sPattern = MetaModel::GetConfig()->Get('cas_profile_pattern');
     foreach ($aGroups as $sGroupName) {
         if (preg_match($sPattern, $sGroupName, $aMatches)) {
             if (array_key_exists(strtolower($aMatches[1]), $aAllProfiles)) {
                 $aProfiles[] = $aAllProfiles[strtolower($aMatches[1])];
                 phpCAS::log("Info: Adding the profile '{$aMatches[1]}' from CAS.");
             } else {
                 phpCAS::log("Warning: {$aMatches[1]} is not a valid iTop profile (extracted from group name: '{$sGroupName}'). Ignored.");
             }
         } else {
             phpCAS::log("Info: The CAS group '{$sGroupName}' does not seem to match an iTop pattern. Ignored.");
         }
     }
     if (count($aProfiles) == 0) {
         phpCAS::log("Info: The user '" . $oUser->GetName() . "' has no profiles retrieved from CAS. Default profile(s) will be used.");
         // Second attempt: check if there is/are valid default profile(s)
         $sCASDefaultProfiles = MetaModel::GetConfig()->Get('cas_default_profiles');
         $aCASDefaultProfiles = explode(';', $sCASDefaultProfiles);
         foreach ($aCASDefaultProfiles as $sDefaultProfileName) {
             if (array_key_exists(strtolower($sDefaultProfileName), $aAllProfiles)) {
                 $aProfiles[] = $aAllProfiles[strtolower($sDefaultProfileName)];
                 phpCAS::log("Info: Adding the default profile '" . $aAllProfiles[strtolower($sDefaultProfileName)] . "' from CAS.");
             } else {
                 phpCAS::log("Warning: the default profile {$sDefaultProfileName} is not a valid iTop profile. Ignored.");
             }
         }
         if (count($aProfiles) == 0) {
             phpCAS::log("Error: The user '" . $oUser->GetName() . "' has no profiles in iTop, and therefore cannot be created.");
             return false;
         }
     }
     // Now synchronize the profiles
     $oProfilesSet = DBObjectSet::FromScratch('URP_UserProfile');
     foreach ($aProfiles as $iProfileId) {
         $oLink = new URP_UserProfile();
         $oLink->Set('profileid', $iProfileId);
         $oLink->Set('reason', 'CAS/LDAP Synchro');
         $oProfilesSet->AddObject($oLink);
     }
     $oUser->Set('profile_list', $oProfilesSet);
     phpCAS::log("Info: the user '" . $oUser->GetName() . "' (id=" . $oUser->GetKey() . ") now has the following profiles: '" . implode("', '", $aProfiles) . "'.");
     if ($oUser->IsModified()) {
         $oMyChange = MetaModel::NewObject("CMDBChange");
         $oMyChange->Set("date", time());
         $oMyChange->Set("userinfo", 'CAS/LDAP Synchro');
         $oMyChange->DBInsert();
         if ($oUser->IsNew()) {
             $oUser->DBInsertTracked($oMyChange);
         } else {
             $oUser->DBUpdateTracked($oMyChange);
         }
     }
     return true;
 }
Example #5
0
 protected function DoExecute()
 {
     CMDBSource::Query('START TRANSACTION');
     //CMDBSource::Query('ROLLBACK'); automatique !
     ////////////////////////////////////////////////////////////////////////////////
     // Set the stage
     //
     $oProvider = new Organization();
     $oProvider->Set('name', 'Test-Provider1');
     $oProvider->DBInsert();
     $iProvider = $oProvider->GetKey();
     $oDM1 = new DeliveryModel();
     $oDM1->Set('name', 'Test-DM-1');
     $oDM1->Set('org_id', $iProvider);
     $oDM1->DBInsert();
     $iDM1 = $oDM1->GetKey();
     $oDM2 = new DeliveryModel();
     $oDM2->Set('name', 'Test-DM-2');
     $oDM2->Set('org_id', $iProvider);
     $oDM2->DBInsert();
     $iDM2 = $oDM2->GetKey();
     ////////////////////////////////////////////////////////////////////////////////
     // Scenarii
     //
     $aScenarii = array(array('description' => 'Add the first customer', 'organizations' => array(array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Remove the customer by loading an empty set', 'organizations' => array(), 'expected-res' => array(), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Create two customers at once', 'organizations' => array(array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1'), array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1", "Test-Customer-2, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Move Customer-1 to the second Delivery Model', 'organizations' => array(array('id' => "SELECT Organization WHERE name='Test-Customer-1'", 'deliverymodel_id' => $iDM2, 'name' => 'Test-Customer-1'), array('deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-2, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0), array('description' => 'Move Customer-1 back to the first Delivery Model and reset Customer-2 (no Delivery Model)', 'organizations' => array(array('id' => "SELECT Organization WHERE name='Test-Customer-1'", 'deliverymodel_id' => $iDM1, 'name' => 'Test-Customer-1'), array('id' => "SELECT Organization WHERE name='Test-Customer-2'", 'deliverymodel_id' => 0, 'name' => 'Test-Customer-2')), 'expected-res' => array("Test-Customer-1, , active, 0, , {$iDM1}, Test-DM-1, , Test-DM-1"), 'history_added' => 0, 'history_removed' => 0, 'history_modified' => 0));
     foreach ($aScenarii as $aScenario) {
         echo "<h4>" . $aScenario['description'] . "</h4>\n";
         $oChange = MetaModel::NewObject("CMDBChange");
         $oChange->Set("date", time());
         $oChange->Set("userinfo", CMDBChange::GetCurrentUserName());
         $oChange->Set("origin", 'custom-extension');
         $oChange->DBInsert();
         CMDBObject::SetCurrentChange($oChange);
         $iChange = $oChange->GetKey();
         // Prepare set
         $oLinkset = DBObjectSet::FromScratch('Organization');
         foreach ($aScenario['organizations'] as $aOrgData) {
             if (array_key_exists('id', $aOrgData)) {
                 $sOQL = $aOrgData['id'];
                 $oSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL));
                 $oOrg = $oSet->Fetch();
                 if (!is_object($oOrg)) {
                     throw new Exception('Failed to find the Organization: ' . $sOQL);
                 }
             } else {
                 $oOrg = MetaModel::NewObject('Organization');
             }
             foreach ($aOrgData as $sAttCode => $value) {
                 if ($sAttCode == 'id') {
                     continue;
                 }
                 $oOrg->Set($sAttCode, $value);
             }
             $oLinkset->AddObject($oOrg);
         }
         // Write
         $oDM = MetaModel::GetObject('DeliveryModel', $iDM1);
         $oDM->Set('customers_list', $oLinkset);
         $oDM->DBWrite();
         // Check Results
         $bFoundIssue = false;
         $oDM = MetaModel::GetObject('DeliveryModel', $iDM1);
         $oLinkset = $oDM->Get('customers_list');
         $aRes = $this->StandardizedDump($oLinkset, 'zzz');
         $sRes = var_export($aRes, true);
         echo "Found: <pre>" . $sRes . "</pre>\n";
         $sExpectedRes = var_export($aScenario['expected-res'], true);
         if ($sRes != $sExpectedRes) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: <pre>" . $sExpectedRes . "</pre>\n";
         }
         // Check History
         $aQueryParams = array('change' => $iChange, 'objclass' => get_class($oDM), 'objkey' => $oDM->GetKey());
         $oAdded = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksAddRemove WHERE objclass = :objclass AND objkey = :objkey AND change = :change AND type = 'added'"), array(), $aQueryParams);
         echo "added: " . $oAdded->Count() . "<br/>\n";
         if ($aScenario['history_added'] != $oAdded->Count()) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_added'] . "<br/>\n";
         }
         $oRemoved = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksAddRemove WHERE objclass = :objclass AND objkey = :objkey AND change = :change AND type = 'removed'"), array(), $aQueryParams);
         echo "removed: " . $oRemoved->Count() . "<br/>\n";
         if ($aScenario['history_removed'] != $oRemoved->Count()) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_removed'] . "<br/>\n";
         }
         $oModified = new DBObjectSet(DBSearch::FromOQL("SELECT CMDBChangeOpSetAttributeLinksTune WHERE objclass = :objclass AND objkey = :objkey AND change = :change"), array(), $aQueryParams);
         echo "modified: " . $oModified->Count() . "<br/>\n";
         if ($aScenario['history_modified'] != $oModified->Count()) {
             $bFoundIssue = true;
             echo "NOT COMPLIANT!!! Expecting: " . $aScenario['history_modified'] . "<br/>\n";
         }
         if ($bFoundIssue) {
             throw new Exception('Stopping on failed scenario');
         }
     }
 }
Example #6
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);
 }
 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);
 }