public static function GetProfileActionGrant($iProfileId, $sClass, $sAction)
 {
     $bLegacyBehavior = MetaModel::GetConfig()->Get('user_rights_legacy');
     // Search for a grant, stoping if any deny is encountered (allowance implies the verification of all paths)
     $bAllow = null;
     // 1 - The class itself
     //
     $sGrantKey = $iProfileId . '_' . $sClass . '_' . $sAction;
     if (isset(self::$aGRANTS[$sGrantKey])) {
         $bAllow = self::$aGRANTS[$sGrantKey];
         if ($bLegacyBehavior) {
             return $bAllow;
         }
         if (!$bAllow) {
             return false;
         }
     }
     // 2 - The parent classes, up to the root class
     //
     foreach (MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false) as $sParent) {
         $sGrantKey = $iProfileId . '_' . $sParent . '+_' . $sAction;
         if (isset(self::$aGRANTS[$sGrantKey])) {
             $bAllow = self::$aGRANTS[$sGrantKey];
             if ($bLegacyBehavior) {
                 return $bAllow;
             }
             if (!$bAllow) {
                 return false;
             }
         }
     }
     // 3 - The related classes (if the current is an N-N link with DEL_AUTO/DEL_SILENT)
     //
     $bGrant = self::GetLinkActionGrant($iProfileId, $sClass, $sAction);
     if (!is_null($bGrant)) {
         $bAllow = $bGrant;
         if ($bLegacyBehavior) {
             return $bAllow;
         }
         if (!$bAllow) {
             return false;
         }
     }
     // 4 - All
     //
     $sGrantKey = $iProfileId . '_*_' . $sAction;
     if (isset(self::$aGRANTS[$sGrantKey])) {
         $bAllow = self::$aGRANTS[$sGrantKey];
         if ($bLegacyBehavior) {
             return $bAllow;
         }
         if (!$bAllow) {
             return false;
         }
     }
     // null or true
     return $bAllow;
 }
 public static function GetProfileActionGrant($iProfileId, $sClass, $sAction)
 {
     // Search for a grant, starting from the most explicit declaration,
     // then searching for less and less explicit declaration
     // 1 - The class itself
     //
     $sGrantKey = $iProfileId . '_' . $sClass . '_' . $sAction;
     if (isset(self::$aGRANTS[$sGrantKey])) {
         return self::$aGRANTS[$sGrantKey];
     }
     // 2 - The parent classes, up to the root class
     //
     foreach (MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_EXCLUDELEAF, false) as $sParent) {
         $sGrantKey = $iProfileId . '_' . $sParent . '+_' . $sAction;
         if (isset(self::$aGRANTS[$sGrantKey])) {
             return self::$aGRANTS[$sGrantKey];
         }
     }
     // 3 - The related classes (if the current is an N-N link with AUTO_DEL)
     //
     if (array_key_exists($sClass, self::$aLINKTOCLASSES)) {
         // Get the grant for the remote classes. The resulting grant is:
         // - One YES => YES
         // - 100% undefined => undefined
         // - otherwise => NO
         //
         // Having write allowed on the remote class implies write + delete on the N-N link class
         if ($sAction == 'd') {
             $sRemoteAction = 'w';
         } elseif ($sAction == 'bd') {
             $sRemoteAction = 'bw';
         } else {
             $sRemoteAction = $sAction;
         }
         foreach (self::$aLINKTOCLASSES[$sClass] as $sRemoteClass) {
             $bUndefined = true;
             $bGrant = self::GetProfileActionGrant($iProfileId, $sRemoteClass, $sAction);
             if ($bGrant === true) {
                 return true;
             }
             if ($bGrant === false) {
                 $bUndefined = false;
             }
         }
         if (!$bUndefined) {
             return false;
         }
     }
     // 4 - All
     //
     $sGrantKey = $iProfileId . '_*_' . $sAction;
     if (isset(self::$aGRANTS[$sGrantKey])) {
         return self::$aGRANTS[$sGrantKey];
     }
     // Still undefined for this class
     return null;
 }
 public function Process($iTimeLimit)
 {
     $aList = array();
     foreach (MetaModel::GetClasses() as $sClass) {
         foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
             if ($oAttDef instanceof AttributeStopWatch) {
                 foreach ($oAttDef->ListThresholds() as $iThreshold => $aThresholdData) {
                     $iPercent = $aThresholdData['percent'];
                     // could be different than the index !
                     $sNow = date('Y-m-d H:i:s');
                     $sExpression = "SELECT {$sClass} WHERE {$sAttCode}_laststart AND {$sAttCode}_{$iThreshold}_triggered = 0 AND {$sAttCode}_{$iThreshold}_deadline < '{$sNow}'";
                     $oFilter = DBObjectSearch::FromOQL($sExpression);
                     $oSet = new DBObjectSet($oFilter);
                     while (time() < $iTimeLimit && ($oObj = $oSet->Fetch())) {
                         $sClass = get_class($oObj);
                         $aList[] = $sClass . '::' . $oObj->GetKey() . ' ' . $sAttCode . ' ' . $iThreshold;
                         // Execute planned actions
                         //
                         foreach ($aThresholdData['actions'] as $aActionData) {
                             $sVerb = $aActionData['verb'];
                             $aParams = $aActionData['params'];
                             $aValues = array();
                             foreach ($aParams as $def) {
                                 if (is_string($def)) {
                                     // Old method (pre-2.1.0) non typed parameters
                                     $aValues[] = $def;
                                 } else {
                                     $sParamType = array_key_exists('type', $def) ? $def['type'] : 'string';
                                     switch ($sParamType) {
                                         case 'int':
                                             $value = (int) $def['value'];
                                             break;
                                         case 'float':
                                             $value = (double) $def['value'];
                                             break;
                                         case 'bool':
                                             $value = (bool) $def['value'];
                                             break;
                                         case 'reference':
                                             $value = ${$def['value']};
                                             break;
                                         case 'string':
                                         default:
                                             $value = (string) $def['value'];
                                     }
                                     $aValues[] = $value;
                                 }
                             }
                             $aCallSpec = array($oObj, $sVerb);
                             call_user_func_array($aCallSpec, $aValues);
                         }
                         // Mark the threshold as "triggered"
                         //
                         $oSW = $oObj->Get($sAttCode);
                         $oSW->MarkThresholdAsTriggered($iThreshold);
                         $oObj->Set($sAttCode, $oSW);
                         if ($oObj->IsModified()) {
                             CMDBObject::SetTrackInfo("Automatic - threshold triggered");
                             $oMyChange = CMDBObject::GetCurrentChange();
                             $oObj->DBUpdateTracked($oMyChange, true);
                         }
                         // Activate any existing trigger
                         //
                         $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
                         $oTriggerSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnThresholdReached AS t WHERE t.target_class IN ('{$sClassList}') AND stop_watch_code=:stop_watch_code AND threshold_index = :threshold_index"), array(), array('stop_watch_code' => $sAttCode, 'threshold_index' => $iThreshold));
                         while ($oTrigger = $oTriggerSet->Fetch()) {
                             $oTrigger->DoActivate($oObj->ToArgs('this'));
                         }
                     }
                 }
             }
         }
     }
     $iProcessed = count($aList);
     return "Triggered {$iProcessed} threshold(s):" . implode(", ", $aList);
 }
 /**
  * Updates the object form POSTED arguments, and writes it into the DB (applies a stimuli if requested)
  * @param DBObject $oObj The object to update
  * $param array $aAttList If set, this will limit the list of updated attributes	 
  * @return void
  */
 public function DoUpdateObjectFromPostedForm(DBObject $oObj, $aAttList = null)
 {
     $sTransactionId = utils::ReadPostedParam('transaction_id', '');
     if (!utils::IsTransactionValid($sTransactionId)) {
         throw new TransactionException();
     }
     $sClass = get_class($oObj);
     $sStimulus = trim(utils::ReadPostedParam('apply_stimulus', ''));
     $sTargetState = '';
     if (!empty($sStimulus)) {
         // Compute the target state
         $aTransitions = $oObj->EnumTransitions();
         if (!isset($aTransitions[$sStimulus])) {
             throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $oObj->GetName(), $oObj->GetStateLabel()));
         }
         $sTargetState = $aTransitions[$sStimulus]['target_state'];
     }
     $oObj->UpdateObjectFromPostedForm('', $aAttList, $sTargetState);
     // Optional: apply a stimulus
     //
     if (!empty($sStimulus)) {
         if (!$oObj->ApplyStimulus($sStimulus)) {
             throw new Exception("Cannot apply stimulus '{$sStimulus}' to {$oObj->GetName()}");
         }
     }
     if ($oObj->IsModified()) {
         // Record the change
         //
         $oObj->DBUpdate();
         // Trigger ?
         //
         $aClasses = MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL);
         $sClassList = implode(", ", CMDBSource::Quote($aClasses));
         $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnPortalUpdate AS t WHERE t.target_class IN ({$sClassList})"));
         while ($oTrigger = $oSet->Fetch()) {
             $oTrigger->DoActivate($oObj->ToArgs('this'));
         }
         $this->p("<h1>" . Dict::Format('UI:Class_Object_Updated', MetaModel::GetName(get_class($oObj)), $oObj->GetName()) . "</h1>\n");
     }
     $bLockEnabled = MetaModel::GetConfig()->Get('concurrent_lock_enabled');
     if ($bLockEnabled) {
         // Release the concurrent lock, if any
         $sOwnershipToken = utils::ReadPostedParam('ownership_token', null, false, 'raw_data');
         if ($sOwnershipToken !== null) {
             // We're done, let's release the lock
             iTopOwnershipLock::ReleaseLock(get_class($oObj), $oObj->GetKey(), $sOwnershipToken);
         }
     }
 }
예제 #5
0
 /**
  * Determines if the given DBObject is part of a 'context'
  * @param DBObject $oObj
  * @return boolean
  */
 public function IsPartOfContext(DBObject $oObj, &$aRootCauses)
 {
     $bRet = false;
     $sFinalClass = get_class($oObj);
     $aParentClasses = MetaModel::EnumParentClasses($sFinalClass, ENUM_PARENT_CLASSES_ALL);
     foreach ($aParentClasses as $sClass) {
         if (array_key_exists($sClass, $this->aContextSearches)) {
             foreach ($this->aContextSearches[$sClass] as $aContextQuery) {
                 $aAliases = $aContextQuery['search']->GetSelectedClasses();
                 $aAliasNames = array_keys($aAliases);
                 $sRootCauseAlias = $aAliasNames[1];
                 // 1st column (=0) = object, second column = root cause
                 $oSet = new DBObjectSet($aContextQuery['search'], array(), array('id' => $oObj->GetKey()));
                 while ($aRow = $oSet->FetchAssoc()) {
                     if (!is_null($aRow[$sRootCauseAlias])) {
                         if (!array_key_exists($aContextQuery['key'], $aRootCauses)) {
                             $aRootCauses[$aContextQuery['key']] = array();
                         }
                         $aRootCauses[$aContextQuery['key']][] = $aRow[$sRootCauseAlias];
                         $bRet = true;
                     }
                 }
             }
         }
     }
     return $bRet;
 }
 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
 /**
  * Designed as an action to be called when a stop watch threshold times out
  * or from within the framework	
  */
 public function ApplyStimulus($sStimulusCode, $bDoNotWrite = false)
 {
     $sStateAttCode = MetaModel::GetStateAttributeCode(get_class($this));
     if (empty($sStateAttCode)) {
         return false;
     }
     MyHelpers::CheckKeyInArray('object lifecycle stimulus', $sStimulusCode, MetaModel::EnumStimuli(get_class($this)));
     $aStateTransitions = $this->EnumTransitions();
     if (!array_key_exists($sStimulusCode, $aStateTransitions)) {
         // This simulus has no effect in the current state... do nothing
         return;
     }
     $aTransitionDef = $aStateTransitions[$sStimulusCode];
     // Change the state before proceeding to the actions, this is necessary because an action might
     // trigger another stimuli (alternative: push the stimuli into a queue)
     $sPreviousState = $this->Get($sStateAttCode);
     $sNewState = $aTransitionDef['target_state'];
     $this->Set($sStateAttCode, $sNewState);
     // $aTransitionDef is an
     //    array('target_state'=>..., 'actions'=>array of handlers procs, 'user_restriction'=>TBD
     $bSuccess = true;
     foreach ($aTransitionDef['actions'] as $sActionHandler) {
         // std PHP spec
         $aActionCallSpec = array($this, $sActionHandler);
         if (!is_callable($aActionCallSpec)) {
             throw new CoreException("Unable to call action: " . get_class($this) . "::{$sActionHandler}");
             return;
         }
         $bRet = call_user_func($aActionCallSpec, $sStimulusCode);
         // if one call fails, the whole is considered as failed
         if (!$bRet) {
             $bSuccess = false;
         }
     }
     if ($bSuccess) {
         $sClass = get_class($this);
         // Stop watches
         foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
             if ($oAttDef instanceof AttributeStopWatch) {
                 $oSW = $this->Get($sAttCode);
                 if (in_array($sNewState, $oAttDef->GetStates())) {
                     $oSW->Start($this, $oAttDef);
                 } else {
                     $oSW->Stop($this, $oAttDef);
                 }
                 $this->Set($sAttCode, $oSW);
             }
         }
         if (!$bDoNotWrite) {
             $this->DBWrite();
         }
         // Change state triggers...
         $sClassList = implode("', '", MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL));
         $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateLeave AS t WHERE t.target_class IN ('{$sClassList}') AND t.state='{$sPreviousState}'"));
         while ($oTrigger = $oSet->Fetch()) {
             $oTrigger->DoActivate($this->ToArgs('this'));
         }
         $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT TriggerOnStateEnter AS t WHERE t.target_class IN ('{$sClassList}') AND t.state='{$sNewState}'"));
         while ($oTrigger = $oSet->Fetch()) {
             $oTrigger->DoActivate($this->ToArgs('this'));
         }
     }
     return $bSuccess;
 }
 /**
  * Get the context definitions from the parameters / configuration. The format of the "key" string is:
  * <module>/relation_context/<class>/<relation>/<direction>
  * The values will be retrieved for the given class and all its parents and merged together as a single array.
  * Entries with an invalid query are removed from the list.
  * @param string $sContextKey The key to fetch the queries in the configuration. Example: itop-tickets/relation_context/UserRequest/impacts/down
  * @param bool $bDevelopParams Whether or not to substitute the parameters inside the queries with the supplied "context params"
  * @param array $aContextParams Arguments for the queries (via ToArgs()) if $bDevelopParams == true
  * @return multitype:multitype:string
  */
 public static function GetContextDefinitions($sContextKey, $bDevelopParams = true, $aContextParams = array())
 {
     $aContextDefs = array();
     $aLevels = explode('/', $sContextKey);
     if (count($aLevels) < 5) {
         IssueLog::Warning("GetContextDefinitions: invalid 'sContextKey' = '{$sContextKey}'. 5 levels of / are expected !");
     } else {
         $sLeafClass = $aLevels[2];
         if (!MetaModel::IsValidClass($sLeafClass)) {
             IssueLog::Warning("GetContextDefinitions: invalid 'sLeafClass' = '{$sLeafClass}'. A valid class name is expected in 3rd position inside '{$sContextKey}' !");
         } else {
             $aRelationContext = MetaModel::GetConfig()->GetModuleSetting($aLevels[0], $aLevels[1], array());
             foreach (MetaModel::EnumParentClasses($sLeafClass, ENUM_PARENT_CLASSES_ALL) as $sClass) {
                 if (isset($aRelationContext[$sClass][$aLevels[3]][$aLevels[4]]['items'])) {
                     $aContextDefs = array_merge($aContextDefs, $aRelationContext[$sClass][$aLevels[3]][$aLevels[4]]['items']);
                 }
             }
             // Check if the queries are valid
             foreach ($aContextDefs as $sKey => $sDefs) {
                 $sOQL = $aContextDefs[$sKey]['oql'];
                 try {
                     // Expand the parameters. If anything goes wrong, then the query is considered as invalid and removed from the list
                     $oSearch = DBObjectSearch::FromOQL($sOQL);
                     $aContextDefs[$sKey]['oql'] = $oSearch->ToOQL($bDevelopParams, $aContextParams);
                 } catch (Exception $e) {
                     IssueLog::Warning('Invalid OQL query: ' . $sOQL . ' in the parameter ' . $sContextKey);
                     unset($aContextDefs[$sKey]);
                 }
             }
         }
     }
     return $aContextDefs;
 }
예제 #9
0
 /**
  * Report the given object
  * 	 
  * @param int An error code (RestResult::OK is no issue has been found)
  * @param string $sMessage Description of the error if any, an empty string otherwise
  * @param DBObject $oObject The object being reported
  * @param array $aFieldSpec An array of class => attribute codes (Cf. RestUtils::GetFieldList). List of the attributes to be reported.
  * @param boolean $bExtendedOutput Output all of the link set attributes ?
  * @return void
  */
 public function AddObject($iCode, $sMessage, $oObject, $aFieldSpec = null, $bExtendedOutput = false)
 {
     $sClass = get_class($oObject);
     $oObjRes = new ObjectResult($sClass, $oObject->GetKey());
     $oObjRes->code = $iCode;
     $oObjRes->message = $sMessage;
     $aFields = null;
     if (!is_null($aFieldSpec)) {
         // Enum all classes in the hierarchy, starting with the current one
         foreach (MetaModel::EnumParentClasses($sClass, ENUM_PARENT_CLASSES_ALL, false) as $sRefClass) {
             if (array_key_exists($sRefClass, $aFieldSpec)) {
                 $aFields = $aFieldSpec[$sRefClass];
                 break;
             }
         }
     }
     if (is_null($aFields)) {
         // No fieldspec given, or not found...
         $aFields = array('id', 'friendlyname');
     }
     foreach ($aFields as $sAttCode) {
         $oObjRes->AddField($oObject, $sAttCode, $bExtendedOutput);
     }
     $sObjKey = get_class($oObject) . '::' . $oObject->GetKey();
     $this->objects[$sObjKey] = $oObjRes;
 }
예제 #10
0
/**
 * Display the details of a given class of objects
 */
function DisplayClassDetails($oPage, $sClass, $sContext)
{
    $oPage->add("<h2>" . MetaModel::GetName($sClass) . " ({$sClass}) - " . MetaModel::GetClassDescription($sClass) . "</h2>\n");
    if (MetaModel::IsAbstract($sClass)) {
        $oPage->p(Dict::S('UI:Schema:AbstractClass'));
    } else {
        $oPage->p(Dict::S('UI:Schema:NonAbstractClass'));
    }
    //	$oPage->p("<h3>".Dict::S('UI:Schema:ClassHierarchyTitle')."</h3>");
    $aParentClasses = array();
    foreach (MetaModel::EnumParentClasses($sClass) as $sParentClass) {
        $aParentClasses[] = MakeClassHLink($sParentClass, $sContext);
    }
    if (count($aParentClasses) > 0) {
        $sParents = implode(' &gt;&gt; ', $aParentClasses) . " &gt;&gt; <b>{$sClass}</b>";
    } else {
        $sParents = '';
    }
    $oPage->p("[<a href=\"schema.php?operation=list{$sContext}\">" . Dict::S('UI:Schema:AllClasses') . "</a>] {$sParents}");
    if (MetaModel::HasChildrenClasses($sClass)) {
        $oPage->add("<ul id=\"ClassHierarchy\">");
        $oPage->add("<li class=\"closed\">" . $sClass . "\n");
        DisplaySubclasses($oPage, $sClass, $sContext);
        $oPage->add("</li>\n");
        $oPage->add("</ul>\n");
        $oPage->add_ready_script('$("#ClassHierarchy").treeview();');
    }
    $oPage->p('');
    $oPage->AddTabContainer('details');
    $oPage->SetCurrentTabContainer('details');
    // List the attributes of the object
    $aForwardChangeTracking = MetaModel::GetTrackForwardExternalKeys($sClass);
    $aDetails = array();
    foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) {
        if ($oAttDef->IsExternalKey()) {
            $sValue = Dict::Format('UI:Schema:ExternalKey_To', MakeClassHLink($oAttDef->GetTargetClass(), $sContext));
            if (array_key_exists($sAttCode, $aForwardChangeTracking)) {
                $oLinkSet = $aForwardChangeTracking[$sAttCode];
                $sRemoteClass = $oLinkSet->GetHostClass();
                $sValue = $sValue . "<span title=\"Forward changes to {$sRemoteClass}\">*</span>";
            }
        } elseif ($oAttDef->IsLinkSet()) {
            $sValue = MakeClassHLink($oAttDef->GetLinkedClass(), $sContext);
        } else {
            $sValue = $oAttDef->GetDescription();
        }
        $sType = $oAttDef->GetType() . ' (' . $oAttDef->GetTypeDesc() . ')';
        $sOrigin = MetaModel::GetAttributeOrigin($sClass, $sAttCode);
        $sAllowedValues = "";
        $sMoreInfo = "";
        $aCols = array();
        foreach ($oAttDef->GetSQLColumns() as $sCol => $sFieldDesc) {
            $aCols[] = "{$sCol}: {$sFieldDesc}";
        }
        if (count($aCols) > 0) {
            $sCols = implode(', ', $aCols);
            $aMoreInfo = array();
            $aMoreInfo[] = Dict::Format('UI:Schema:Columns_Description', $sCols);
            $aMoreInfo[] = Dict::Format('UI:Schema:Default_Description', $oAttDef->GetDefaultValue());
            $aMoreInfo[] = $oAttDef->IsNullAllowed() ? Dict::S('UI:Schema:NullAllowed') : Dict::S('UI:Schema:NullNotAllowed');
            $sMoreInfo .= implode(', ', $aMoreInfo);
        }
        if ($oAttDef instanceof AttributeEnum) {
            // Display localized values for the enum (which depend on the localization provided by the class)
            $aLocalizedValues = MetaModel::GetAllowedValues_att($sClass, $sAttCode, array());
            $aDescription = array();
            foreach ($aLocalizedValues as $val => $sDisplay) {
                $aDescription[] = htmlentities("{$val} => ", ENT_QUOTES, 'UTF-8') . $sDisplay;
            }
            $sAllowedValues = implode(', ', $aDescription);
        } else {
            $sAllowedValues = '';
        }
        $aDetails[] = array('code' => $oAttDef->GetCode(), 'type' => $sType, 'origin' => $sOrigin, 'label' => $oAttDef->GetLabel(), 'description' => $sValue, 'values' => $sAllowedValues, 'moreinfo' => $sMoreInfo);
    }
    $oPage->SetCurrentTab(Dict::S('UI:Schema:Attributes'));
    $aConfig = array('code' => array('label' => Dict::S('UI:Schema:AttributeCode'), 'description' => Dict::S('UI:Schema:AttributeCode+')), 'label' => array('label' => Dict::S('UI:Schema:Label'), 'description' => Dict::S('UI:Schema:Label+')), 'type' => array('label' => Dict::S('UI:Schema:Type'), 'description' => Dict::S('UI:Schema:Type+')), 'origin' => array('label' => Dict::S('UI:Schema:Origin'), 'description' => Dict::S('UI:Schema:Origin+')), 'description' => array('label' => Dict::S('UI:Schema:Description'), 'description' => Dict::S('UI:Schema:Description+')), 'values' => array('label' => Dict::S('UI:Schema:AllowedValues'), 'description' => Dict::S('UI:Schema:AllowedValues+')), 'moreinfo' => array('label' => Dict::S('UI:Schema:MoreInfo'), 'description' => Dict::S('UI:Schema:MoreInfo+')));
    $oPage->table($aConfig, $aDetails);
    // List the search criteria for this object
    $aDetails = array();
    foreach (MetaModel::GetClassFilterDefs($sClass) as $sFilterCode => $oFilterDef) {
        $aOpDescs = array();
        foreach ($oFilterDef->GetOperators() as $sOpCode => $sOpDescription) {
            $sIsTheLooser = $sOpCode == $oFilterDef->GetLooseOperator() ? " (loose search)" : "";
            $aOpDescs[] = "{$sOpCode} ({$sOpDescription}){$sIsTheLooser}";
        }
        $aDetails[] = array('code' => $sFilterCode, 'description' => $oFilterDef->GetLabel(), 'operators' => implode(" / ", $aOpDescs));
    }
    $oPage->SetCurrentTab(Dict::S('UI:Schema:SearchCriteria'));
    $aConfig = array('code' => array('label' => Dict::S('UI:Schema:FilterCode'), 'description' => Dict::S('UI:Schema:FilterCode+')), 'description' => array('label' => Dict::S('UI:Schema:FilterDescription'), 'description' => Dict::S('UI:Schema:FilterDescription+')), 'operators' => array('label' => Dict::S('UI:Schema:AvailOperators'), 'description' => Dict::S('UI:Schema:AvailOperators+')));
    $oPage->table($aConfig, $aDetails);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:ChildClasses'));
    DisplaySubclasses($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:ReferencingClasses'));
    DisplayReferencingClasses($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:RelatedClasses'));
    DisplayRelatedClasses($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:LifeCycle'));
    DisplayLifecycle($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab(Dict::S('UI:Schema:Triggers'));
    DisplayTriggers($oPage, $sClass, $sContext);
    $oPage->SetCurrentTab();
    $oPage->SetCurrentTabContainer();
}
 /**
  * Store an object in the database and remember the mapping
  * between its original ID and the newly created ID in the database
  */
 protected function StoreObject($sClass, $oTargetObj, $iSrcId, $bSearch = false, $bUpdateKeyCacheOnly = false)
 {
     $iObjId = 0;
     try {
         if ($bSearch) {
             // Check if the object does not already exist, based on its usual reconciliation keys...
             $aReconciliationKeys = MetaModel::GetReconcKeys($sClass);
             if (count($aReconciliationKeys) > 0) {
                 // Some reconciliation keys have been defined, use them to search for the object
                 $oSearch = new DBObjectSearch($sClass);
                 $iConditionsCount = 0;
                 foreach ($aReconciliationKeys as $sAttCode) {
                     if ($oTargetObj->Get($sAttCode) != '') {
                         $oSearch->AddCondition($sAttCode, $oTargetObj->Get($sAttCode), '=');
                         $iConditionsCount++;
                     }
                 }
                 if ($iConditionsCount > 0) {
                     $oSet = new DBObjectSet($oSearch);
                     if ($oSet->count() == 1) {
                         // The object already exists, reuse it
                         $oExistingObject = $oSet->Fetch();
                         $iObjId = $oExistingObject->GetKey();
                     }
                 }
             }
         }
         if ($iObjId == 0) {
             if ($oTargetObj->IsNew()) {
                 if (!$bUpdateKeyCacheOnly) {
                     $iObjId = $oTargetObj->DBInsertNoReload();
                     $this->m_iCountCreated++;
                 }
             } else {
                 $iObjId = $oTargetObj->GetKey();
                 if (!$bUpdateKeyCacheOnly) {
                     $oTargetObj->DBUpdate();
                 }
             }
         }
     } catch (Exception $e) {
         SetupPage::log_error("An object could not be recorded - {$sClass}/{$iSrcId} - " . $e->getMessage());
         $this->m_aErrors[] = "An object could not be recorded - {$sClass}/{$iSrcId} - " . $e->getMessage();
     }
     $aParentClasses = MetaModel::EnumParentClasses($sClass);
     $aParentClasses[] = $sClass;
     foreach ($aParentClasses as $sObjClass) {
         $this->m_aKeys[$sObjClass][$iSrcId] = $iObjId;
     }
     $this->m_aObjectsCache[$sClass][$iObjId] = $oTargetObj;
 }
예제 #12
0
 /**
  * Get the context definitions from the parameters / configuration. The format of the "key" string is:
  * <module>/relation_context/<class>/<relation>/<direction>
  * The values will be retrieved for the given class and all its parents and merged together as a single array.
  * Entries with an invalid query are removed from the list.
  * @param string $sContextKey The key to fetch the queries in the configuration. Example: itop-tickets/relation_context/UserRequest/impacts/down
  * @param bool $bDevelopParams Whether or not to substitute the parameters inside the queries with the supplied "context params"
  * @param array $aContextParams Arguments for the queries (via ToArgs()) if $bDevelopParams == true
  * @return multitype:multitype:string
  */
 public function GetContextDefinitions($sContextKey, $bDevelopParams = true, $aContextParams = array())
 {
     $aLevels = explode('/', $sContextKey);
     $sLeafClass = $aLevels[2];
     $aRelationContext = MetaModel::GetConfig()->GetModuleSetting($aLevels[0], $aLevels[1], array());
     $aContextDefs = array();
     foreach (MetaModel::EnumParentClasses($sLeafClass, ENUM_PARENT_CLASSES_ALL) as $sClass) {
         if (isset($aRelationContext[$sClass][$aLevels[3]][$aLevels[4]]['items'])) {
             $aContextDefs = array_merge($aContextDefs, $aRelationContext[$sClass][$aLevels[3]][$aLevels[4]]['items']);
         }
     }
     // Check if the queries are valid
     foreach ($aContextDefs as $sKey => $sDefs) {
         $sOQL = $aContextDefs[$sKey]['oql'];
         try {
             // Expand the parameters. If anything goes wrong, then the query is considered as invalid and removed from the list
             $oSearch = DBObjectSearch::FromOQL($sOQL);
             $aContextDefs[$sKey]['oql'] = $oSearch->ToOQL($bDevelopParams, $aContextParams);
         } catch (Exception $e) {
             unset($aContextDefs[$sKey]);
         }
     }
     return $aContextDefs;
 }