/** * Helper to generate a Graphviz code for displaying the life cycle of a class * @param string $sClass The class to display * @return string The Graph description in Graphviz/Dot syntax */ function GraphvizLifecycle($sClass) { $sDotFileContent = ""; $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); if (empty($sStateAttCode)) { //$oPage->p("no lifecycle for this class"); } else { $aStates = MetaModel::EnumStates($sClass); $aStimuli = MetaModel::EnumStimuli($sClass); $sDotFileContent .= "digraph finite_state_machine {\r\n\tgraph [bgcolor = \"transparent\"];\r\n\trankdir=LR;\r\n\tsize=\"12,12\"\r\n\tnode [ fontname=Verdana style=filled fillcolor=\"#ffffff\" ];\r\n\tedge [ fontname=Verdana ];\r\n"; $aStatesLinks = array(); foreach ($aStates as $sStateCode => $aStateDef) { $aStatesLinks[$sStateCode] = array('in' => 0, 'out' => 0); } foreach ($aStates as $sStateCode => $aStateDef) { $sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode); $sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode); foreach (MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef) { $aStatesLinks[$sStateCode]['out']++; $aStatesLinks[$aTransitionDef['target_state']]['in']++; $sStimulusLabel = $aStimuli[$sStimulusCode]->GetLabel(); $sTargetStateLabel = MetaModel::GetStateLabel($sClass, $aTransitionDef['target_state']); $sDotFileContent .= "\t{$sStateCode} -> {$aTransitionDef['target_state']} [ label=\"" . GraphvizEscape($sStimulusLabel) . "\"];\n"; } } foreach ($aStates as $sStateCode => $aStateDef) { if ($aStatesLinks[$sStateCode]['out'] > 0 || $aStatesLinks[$sStateCode]['in'] > 0) { // Show only reachable states $sStateLabel = str_replace(' ', '\\n', MetaModel::GetStateLabel($sClass, $sStateCode)); if ($aStatesLinks[$sStateCode]['in'] == 0 || $aStatesLinks[$sStateCode]['out'] == 0) { // End or Start state, make it look different $sDotFileContent .= "\t{$sStateCode} [ shape=doublecircle,label=\"" . GraphvizEscape($sStateLabel) . "\"];\n"; } else { $sDotFileContent .= "\t{$sStateCode} [ shape=circle,label=\"" . GraphvizEscape($sStateLabel) . "\"];\n"; } } } $sDotFileContent .= "}\n"; } return $sDotFileContent; }
/** * Apply the 'next-action' to the given object or redirect to the page that prompts for additional information if needed * @param $oP WebPage The page for the output * @param $oObj CMDBObject The object to process * @param $sNextAction string The code of the stimulus for the 'action' (i.e. Transition) to apply */ function ApplyNextAction(Webpage $oP, CMDBObject $oObj, $sNextAction) { // Here handle the apply stimulus $aTransitions = $oObj->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli(get_class($oObj)); if (!isset($aTransitions[$sNextAction])) { // Invalid stimulus throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sNextAction, $oObj->GetName(), $oObj->GetStateLabel())); } // Get the list of missing mandatory fields for the target state, considering only the changes from the previous form (i.e don't prompt twice) $aExpectedAttributes = $oObj->GetExpectedAttributes($oObj->GetState(), $sNextAction, true); if (count($aExpectedAttributes) == 0) { // If all the mandatory fields are already present, just apply the transition silently... if ($oObj->ApplyStimulus($sNextAction)) { $oObj->DBUpdate(); } ReloadAndDisplay($oP, $oObj); } else { // redirect to the 'stimulus' action $oAppContext = new ApplicationContext(); //echo "<p>Missing Attributes <pre>".print_r($aExpectedAttributes, true)."</pre></p>\n"; $oP->add_header('Location: ' . utils::GetAbsoluteUrlAppRoot() . 'pages/UI.php?operation=stimulus&class=' . get_class($oObj) . '&stimulus=' . $sNextAction . '&id=' . $oObj->getKey() . '&' . $oAppContext->GetForLink()); } }
public function GetExpectedAttributes($sCurrentState, $sStimulus, $bOnlyNewOnes) { $aTransitions = $this->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli(get_class($this)); if (!isset($aTransitions[$sStimulus])) { // Invalid stimulus throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulus, $this->GetName(), $this->GetStateLabel())); } $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['target_state']; $aTargetStates = MetaModel::EnumStates(get_class($this)); $aTargetState = $aTargetStates[$sTargetState]; $aCurrentState = $aTargetStates[$this->GetState()]; $aExpectedAttributes = $aTargetState['attribute_list']; $aCurrentAttributes = $aCurrentState['attribute_list']; $aComputedAttributes = array(); foreach ($aExpectedAttributes as $sAttCode => $iExpectCode) { if (!array_key_exists($sAttCode, $aCurrentAttributes)) { $aComputedAttributes[$sAttCode] = $iExpectCode; } else { if (!($aCurrentAttributes[$sAttCode] & (OPT_ATT_HIDDEN | OPT_ATT_READONLY))) { $iExpectCode = $iExpectCode & ~(OPT_ATT_MUSTPROMPT | OPT_ATT_MUSTCHANGE); // Already prompted/changed, reset the flags } //TODO: better check if the attribute is not *null* if ($iExpectCode & OPT_ATT_MANDATORY && $this->Get($sAttCode) != '') { $iExpectCode = $iExpectCode & ~OPT_ATT_MANDATORY; // If the attribute is present, then no need to request its presence } $aComputedAttributes[$sAttCode] = $iExpectCode; } $aComputedAttributes[$sAttCode] = $aComputedAttributes[$sAttCode] & ~(OPT_ATT_READONLY | OPT_ATT_HIDDEN); // Don't care about this form now if ($aComputedAttributes[$sAttCode] == 0) { unset($aComputedAttributes[$sAttCode]); } } return $aComputedAttributes; }
function DoShowGrantSumary($oPage) { if ($this->GetRawName() == "Administrator") { // Looks dirty, but ok that's THE ONE $oPage->p(Dict::S('UI:UserManagement:AdminProfile+')); return; } // Note: for sure, we assume that the instance is derived from UserRightsProjection $oUserRights = UserRights::GetModuleInstance(); $aDisplayData = array(); foreach (MetaModel::GetClasses('bizmodel') as $sClass) { // Skip non instantiable classes if (MetaModel::IsAbstract($sClass)) { continue; } $aStimuli = array(); foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) { $oGrant = $oUserRights->GetClassStimulusGrant($this->GetKey(), $sClass, $sStimulusCode); if (is_object($oGrant) && $oGrant->Get('permission') == 'yes') { $aStimuli[] = '<span title="' . $sStimulusCode . ': ' . htmlentities($oStimulus->GetDescription(), ENT_QUOTES, 'UTF-8') . '">' . htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8') . '</span>'; } } $sStimuli = implode(', ', $aStimuli); $aDisplayData[] = array('class' => MetaModel::GetName($sClass), 'read' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Read'), 'bulkread' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Read'), 'write' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Modify'), 'bulkwrite' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Modify'), 'delete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Delete'), 'bulkdelete' => $this->GetGrantAsHtml($oUserRights, $sClass, 'Bulk Delete'), 'stimuli' => $sStimuli); } $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+')); $aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+')); $aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+')); $aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+')); $aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+')); $aDisplayConfig['delete'] = array('label' => Dict::S('UI:UserManagement:Action:Delete'), 'description' => Dict::S('UI:UserManagement:Action:Delete+')); $aDisplayConfig['bulkdelete'] = array('label' => Dict::S('UI:UserManagement:Action:BulkDelete'), 'description' => Dict::S('UI:UserManagement:Action:BulkDelete+')); $aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+')); $oPage->table($aDisplayConfig, $aDisplayData); }
/** * 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; }
protected function SetupUser($iUserId, $bNewUser = false) { foreach (array('bizmodel', 'application', 'gui', 'core/cmdb') as $sCategory) { foreach (MetaModel::GetClasses($sCategory) as $sClass) { foreach (self::$m_aActionCodes as $iActionCode => $sAction) { if ($bNewUser) { $bAddCell = true; } else { $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassGrant WHERE class = '{$sClass}' AND action = '{$sAction}' AND userid = {$iUserId}")); $bAddCell = $oSet->Count() < 1; } if ($bAddCell) { // Create a new entry $oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassGrant"); $oMyClassGrant->Set("userid", $iUserId); $oMyClassGrant->Set("class", $sClass); $oMyClassGrant->Set("action", $sAction); $oMyClassGrant->Set("permission", "yes"); $iId = $oMyClassGrant->DBInsertNoReload(); } } foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) { if ($bNewUser) { $bAddCell = true; } else { $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixClassStimulusGrant WHERE class = '{$sClass}' AND stimulus = '{$sStimulusCode}' AND userid = {$iUserId}")); $bAddCell = $oSet->Count() < 1; } if ($bAddCell) { // Create a new entry $oMyClassGrant = MetaModel::NewObject("UserRightsMatrixClassStimulusGrant"); $oMyClassGrant->Set("userid", $iUserId); $oMyClassGrant->Set("class", $sClass); $oMyClassGrant->Set("stimulus", $sStimulusCode); $oMyClassGrant->Set("permission", "yes"); $iId = $oMyClassGrant->DBInsertNoReload(); } } foreach (MetaModel::GetAttributesList($sClass) as $sAttCode) { if ($bNewUser) { $bAddCell = true; } else { $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT UserRightsMatrixAttributeGrant WHERE class = '{$sClass}' AND attcode = '{$sAttCode}' AND userid = {$iUserId}")); $bAddCell = $oSet->Count() < 1; } if ($bAddCell) { foreach (array('read', 'modify') as $sAction) { // Create a new entry $oMyAttGrant = MetaModel::NewObject("UserRightsMatrixAttributeGrant"); $oMyAttGrant->Set("userid", $iUserId); $oMyAttGrant->Set("class", $sClass); $oMyAttGrant->Set("attcode", $sAttCode); $oMyAttGrant->Set("action", $sAction); $oMyAttGrant->Set("permission", "yes"); $iId = $oMyAttGrant->DBInsertNoReload(); } } } } } /* // Create the "My Bookmarks" menu item (parent_id = 0, rank = 6) if ($bNewUser) { $bAddMenu = true; } else { $oSet = new DBObjectSet(DBObjectSearch::FromOQL("SELECT menuNode WHERE type = 'user' AND parent_id = 0 AND user_id = $iUserId")); $bAddMenu = ($oSet->Count() < 1); } if ($bAddMenu) { $oMenu = MetaModel::NewObject('menuNode'); $oMenu->Set('type', 'user'); $oMenu->Set('parent_id', 0); // It's a toplevel entry $oMenu->Set('rank', 6); // Located just above the Admin Tools section (=7) $oMenu->Set('name', 'My Bookmarks'); $oMenu->Set('label', 'My Favorite Items'); $oMenu->Set('hyperlink', 'UI.php'); $oMenu->Set('template', '<p></p><p></p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:32px;">My bookmarks</p><p style="text-align:center; font-family:Georgia, Times, serif; font-size:14px;"><i>This section contains my most favorite search results</i></p>'); $oMenu->Set('user_id', $iUserId); $oMenu->DBInsert(); } */ }
/** * Enumerate services delivered by this class * @param string $sVersion The version (e.g. 1.0) supported by the services * @return RestResult The standardized result structure (at least a message) * @throws Exception in case of internal failure. */ public function ExecOperation($sVersion, $sVerb, $aParams) { $oResult = new RestResultWithObjects(); switch ($sVerb) { case 'core/create': RestUtils::InitTrackingComment($aParams); $sClass = RestUtils::GetClass($aParams, 'class'); $aFields = RestUtils::GetMandatoryParam($aParams, 'fields'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $oObject = RestUtils::MakeObjectFromFields($sClass, $aFields); $oObject->DBInsert(); $oResult->AddObject(0, 'created', $oObject, $aShowFields, $bExtendedOutput); break; case 'core/update': RestUtils::InitTrackingComment($aParams); $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $aFields = RestUtils::GetMandatoryParam($aParams, 'fields'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $oObject = RestUtils::FindObjectFromKey($sClass, $key); RestUtils::UpdateObjectFromFields($oObject, $aFields); $oObject->DBUpdate(); $oResult->AddObject(0, 'updated', $oObject, $aShowFields, $bExtendedOutput); break; case 'core/apply_stimulus': RestUtils::InitTrackingComment($aParams); $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $aFields = RestUtils::GetMandatoryParam($aParams, 'fields'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $sStimulus = RestUtils::GetMandatoryParam($aParams, 'stimulus'); $oObject = RestUtils::FindObjectFromKey($sClass, $key); RestUtils::UpdateObjectFromFields($oObject, $aFields); $aTransitions = $oObject->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli(get_class($oObject)); if (!isset($aTransitions[$sStimulus])) { // Invalid stimulus $oResult->code = RestResult::INTERNAL_ERROR; $oResult->message = "Invalid stimulus: '{$sStimulus}' on the object " . $oObject->GetName() . " in state '" . $oObject->GetState() . "'"; } else { $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['target_state']; $aStates = MetaModel::EnumStates($sClass); $aTargetStateDef = $aStates[$sTargetState]; $aExpectedAttributes = $aTargetStateDef['attribute_list']; $aMissingMandatory = array(); foreach ($aExpectedAttributes as $sAttCode => $iExpectCode) { if ($iExpectCode & OPT_ATT_MANDATORY && $oObject->Get($sAttCode) == '') { $aMissingMandatory[] = $sAttCode; } } if (count($aMissingMandatory) == 0) { // If all the mandatory fields are already present, just apply the transition silently... if ($oObject->ApplyStimulus($sStimulus)) { $oObject->DBUpdate(); $oResult->AddObject(0, 'updated', $oObject, $aShowFields, $bExtendedOutput); } } else { // Missing mandatory attributes for the transition $oResult->code = RestResult::INTERNAL_ERROR; $oResult->message = 'Missing mandatory attribute(s) for applying the stimulus: ' . implode(', ', $aMissingMandatory) . '.'; } } break; case 'core/get': $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); while ($oObject = $oObjectSet->Fetch()) { $oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput); } $oResult->message = "Found: " . $oObjectSet->Count(); break; case 'core/delete': $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $bSimulate = RestUtils::GetOptionalParam($aParams, 'simulate', false); $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); $aObjects = $oObjectSet->ToArray(); $this->DeleteObjects($oResult, $aObjects, $bSimulate); break; case 'core/get_related': $oResult = new RestResultWithRelations(); $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $sRelation = RestUtils::GetMandatoryParam($aParams, 'relation'); $iMaxRecursionDepth = RestUtils::GetOptionalParam($aParams, 'depth', 20); $sDirection = RestUtils::GetOptionalParam($aParams, 'direction', null); $bEnableRedundancy = RestUtils::GetOptionalParam($aParams, 'redundancy', false); $bReverse = false; if (is_null($sDirection) && $sRelation == 'depends on') { // Legacy behavior, consider "depends on" as a forward relation $sRelation = 'impacts'; $sDirection = 'up'; $bReverse = true; // emulate the legacy behavior by returning the edges } else { if (is_null($sDirection)) { $sDirection = 'down'; } } $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); if ($sDirection == 'down') { $oRelationGraph = $oObjectSet->GetRelatedObjectsDown($sRelation, $iMaxRecursionDepth, $bEnableRedundancy); } else { if ($sDirection == 'up') { $oRelationGraph = $oObjectSet->GetRelatedObjectsUp($sRelation, $iMaxRecursionDepth, $bEnableRedundancy); } else { $oResult->code = RestResult::INTERNAL_ERROR; $oResult->message = "Invalid value: '{$sDirection}' for the parameter 'direction'. Valid values are 'up' and 'down'"; return $oResult; } } if ($bEnableRedundancy) { // Remove the redundancy nodes from the output $oIterator = new RelationTypeIterator($oRelationGraph, 'Node'); foreach ($oIterator as $oNode) { if ($oNode instanceof RelationRedundancyNode) { $oRelationGraph->FilterNode($oNode); } } } $aIndexByClass = array(); $oIterator = new RelationTypeIterator($oRelationGraph); foreach ($oIterator as $oElement) { if ($oElement instanceof RelationObjectNode) { $oObject = $oElement->GetProperty('object'); if ($oObject) { if ($bEnableRedundancy) { // Add only the "reached" objects if ($oElement->GetProperty('is_reached')) { $aIndexByClass[get_class($oObject)][$oObject->GetKey()] = null; $oResult->AddObject(0, '', $oObject); } } else { $aIndexByClass[get_class($oObject)][$oObject->GetKey()] = null; $oResult->AddObject(0, '', $oObject); } } } else { if ($oElement instanceof RelationEdge) { $oSrcObj = $oElement->GetSourceNode()->GetProperty('object'); $oDestObj = $oElement->GetSinkNode()->GetProperty('object'); $sSrcKey = get_class($oSrcObj) . '::' . $oSrcObj->GetKey(); $sDestKey = get_class($oDestObj) . '::' . $oDestObj->GetKey(); if ($bEnableRedundancy) { // Add only the edges where both source and destination are "reached" if ($oElement->GetSourceNode()->GetProperty('is_reached') && $oElement->GetSinkNode()->GetProperty('is_reached')) { if ($bReverse) { $oResult->AddRelation($sDestKey, $sSrcKey); } else { $oResult->AddRelation($sSrcKey, $sDestKey); } } } else { if ($bReverse) { $oResult->AddRelation($sDestKey, $sSrcKey); } else { $oResult->AddRelation($sSrcKey, $sDestKey); } } } } } if (count($aIndexByClass) > 0) { $aStats = array(); foreach ($aIndexByClass as $sClass => $aIds) { $aStats[] = $sClass . '= ' . count($aIds); } $oResult->message = "Scope: " . $oObjectSet->Count() . "; Related objects: " . implode(', ', $aStats); } else { $oResult->message = "Nothing found"; } break; case 'core/check_credentials': $oResult = new RestResult(); $sUser = RestUtils::GetMandatoryParam($aParams, 'user'); $sPassword = RestUtils::GetMandatoryParam($aParams, 'password'); if (UserRights::CheckCredentials($sUser, $sPassword) !== true) { $oResult->authorized = false; } else { $oResult->authorized = true; } break; default: // unknown operation: handled at a higher level } return $oResult; }
/** * Helper for the lifecycle details of a given class */ function DisplayLifecycle($oPage, $sClass) { $sStateAttCode = MetaModel::GetStateAttributeCode($sClass); if (empty($sStateAttCode)) { $oPage->p(Dict::S('UI:Schema:NoLifeCyle')); } else { $aStates = MetaModel::EnumStates($sClass); $aStimuli = MetaModel::EnumStimuli($sClass); $oPage->add("<img src=\"" . utils::GetAbsoluteUrlAppRoot() . "pages/graphviz.php?class={$sClass}\">\n"); $oPage->add("<h3>" . Dict::S('UI:Schema:LifeCycleTransitions') . "</h3>\n"); $oPage->add("<ul>\n"); foreach ($aStates as $sStateCode => $aStateDef) { $sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode); $sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode); $oPage->add("<li title=\"code: {$sStateCode}\">{$sStateLabel} <span style=\"color:grey;\">({$sStateCode}) {$sStateDescription}</span></li>\n"); $oPage->add("<ul>\n"); foreach (MetaModel::EnumTransitions($sClass, $sStateCode) as $sStimulusCode => $aTransitionDef) { $sStimulusLabel = $aStimuli[$sStimulusCode]->GetLabel(); $sTargetStateLabel = MetaModel::GetStateLabel($sClass, $aTransitionDef['target_state']); if (count($aTransitionDef['actions']) > 0) { $sActions = " <em>(" . implode(', ', $aTransitionDef['actions']) . ")</em>"; } else { $sActions = ""; } $oPage->add("<li><span style=\"color:red;font-weight=bold;\">{$sStimulusLabel}</span> => {$sTargetStateLabel} {$sActions}</li>\n"); } $oPage->add("</ul>\n"); } $oPage->add("</ul>\n"); $oPage->add("<h3>" . Dict::S('UI:Schema:LifeCyleAttributeOptions') . "</h3>\n"); $oPage->add("<ul>\n"); foreach ($aStates as $sStateCode => $aStateDef) { $sStateLabel = MetaModel::GetStateLabel($sClass, $sStateCode); $sStateDescription = MetaModel::GetStateDescription($sClass, $sStateCode); $oPage->add("<li title=\"code: {$sStateCode}\">{$sStateLabel} <span style=\"color:grey;\">({$sStateCode}) {$sStateDescription}</span></li>\n"); if (count($aStates[$sStateCode]['attribute_list']) > 0) { $oPage->add("<ul>\n"); foreach ($aStates[$sStateCode]['attribute_list'] as $sAttCode => $iOptions) { $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $sAttLabel = $oAttDef->GetLabel(); $aOptions = array(); if ($iOptions & OPT_ATT_HIDDEN) { $aOptions[] = Dict::S('UI:Schema:LifeCycleHiddenAttribute'); } if ($iOptions & OPT_ATT_READONLY) { $aOptions[] = Dict::S('UI:Schema:LifeCycleReadOnlyAttribute'); } if ($iOptions & OPT_ATT_MANDATORY) { $aOptions[] = Dict::S('UI:Schema:LifeCycleMandatoryAttribute'); } if ($iOptions & OPT_ATT_MUSTCHANGE) { $aOptions[] = Dict::S('UI:Schema:LifeCycleAttributeMustChange'); } if ($iOptions & OPT_ATT_MUSTPROMPT) { $aOptions[] = Dict::S('UI:Schema:LifeCycleAttributeMustPrompt'); } if (count($aOptions)) { $sOptions = implode(', ', $aOptions); } else { $sOptions = ""; } $oPage->add("<li><span style=\"color:purple;font-weight=bold;\">{$sAttLabel}</span> {$sOptions}</li>\n"); } $oPage->add("</ul>\n"); } else { $oPage->p("<em>" . Dict::S('UI:Schema:LifeCycleEmptyList') . "</em>"); } } $oPage->add("</ul>\n"); } }
function DoShowGrantSumary($oPage, $sClassCategory) { if (UserRights::IsAdministrator($this)) { // Looks dirty, but ok that's THE ONE $oPage->p(Dict::S('UI:UserManagement:AdminProfile+')); return; } $oKPI = new ExecutionKPI(); $aDisplayData = array(); foreach (MetaModel::GetClasses($sClassCategory) as $sClass) { $aClassStimuli = MetaModel::EnumStimuli($sClass); if (count($aClassStimuli) > 0) { $aStimuli = array(); foreach ($aClassStimuli as $sStimulusCode => $oStimulus) { if (UserRights::IsStimulusAllowed($sClass, $sStimulusCode, null, $this)) { $aStimuli[] = '<span title="' . $sStimulusCode . ': ' . htmlentities($oStimulus->GetDescription(), ENT_QUOTES, 'UTF-8') . '">' . htmlentities($oStimulus->GetLabel(), ENT_QUOTES, 'UTF-8') . '</span>'; } } $sStimuli = implode(', ', $aStimuli); } else { $sStimuli = '<em title="' . Dict::S('UI:UserManagement:NoLifeCycleApplicable+') . '">' . Dict::S('UI:UserManagement:NoLifeCycleApplicable') . '</em>'; } $aDisplayData[] = array('class' => MetaModel::GetName($sClass), 'read' => $this->GetGrantAsHtml($sClass, UR_ACTION_READ), 'bulkread' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_READ), 'write' => $this->GetGrantAsHtml($sClass, UR_ACTION_MODIFY), 'bulkwrite' => $this->GetGrantAsHtml($sClass, UR_ACTION_BULK_MODIFY), 'stimuli' => $sStimuli); } $oKPI->ComputeAndReport('Computation of user rights'); $aDisplayConfig = array(); $aDisplayConfig['class'] = array('label' => Dict::S('UI:UserManagement:Class'), 'description' => Dict::S('UI:UserManagement:Class+')); $aDisplayConfig['read'] = array('label' => Dict::S('UI:UserManagement:Action:Read'), 'description' => Dict::S('UI:UserManagement:Action:Read+')); $aDisplayConfig['bulkread'] = array('label' => Dict::S('UI:UserManagement:Action:BulkRead'), 'description' => Dict::S('UI:UserManagement:Action:BulkRead+')); $aDisplayConfig['write'] = array('label' => Dict::S('UI:UserManagement:Action:Modify'), 'description' => Dict::S('UI:UserManagement:Action:Modify+')); $aDisplayConfig['bulkwrite'] = array('label' => Dict::S('UI:UserManagement:Action:BulkModify'), 'description' => Dict::S('UI:UserManagement:Action:BulkModify+')); $aDisplayConfig['stimuli'] = array('label' => Dict::S('UI:UserManagement:Action:Stimuli'), 'description' => Dict::S('UI:UserManagement:Action:Stimuli+')); $oPage->table($aDisplayConfig, $aDisplayData); }
function MakeDictionaryTemplate($sModules = '', $sLanguage = 'EN US') { $sRes = ''; Dict::SetDefaultLanguage($sLanguage); $aAvailableLanguages = Dict::GetLanguages(); $sDesc = $aAvailableLanguages[$sLanguage]['description']; $sLocalizedDesc = $aAvailableLanguages[$sLanguage]['localized_description']; $sRes .= "// Dictionary conventions\n"; $sRes .= htmlentities("// Class:<class_name>\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>+\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>+\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>/Value:<value>\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>/Attribute:<attribute_code>/Value:<value>+\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>/Stimulus:<stimulus_code>\n", ENT_QUOTES, 'UTF-8'); $sRes .= htmlentities("// Class:<class_name>/Stimulus:<stimulus_code>+\n", ENT_QUOTES, 'UTF-8'); $sRes .= "\n"; // Note: I did not use EnumCategories(), because a given class maybe found in several categories // Need to invent the "module", to characterize the origins of a class if (strlen($sModules) == 0) { $aModules = array('bizmodel', 'core/cmdb', 'gui', 'application', 'addon/userrights', 'monitoring'); } else { $aModules = explode(', ', $sModules); } $sRes .= "//////////////////////////////////////////////////////////////////////\n"; $sRes .= "// Note: The classes have been grouped by categories: " . implode(', ', $aModules) . "\n"; $sRes .= "//////////////////////////////////////////////////////////////////////\n"; foreach ($aModules as $sCategory) { $sRes .= "//////////////////////////////////////////////////////////////////////\n"; $sRes .= "// Classes in '{$sCategory}'\n"; $sRes .= "//////////////////////////////////////////////////////////////////////\n"; $sRes .= "//\n"; $sRes .= "\n"; foreach (MetaModel::GetClasses($sCategory) as $sClass) { if (!MetaModel::HasTable($sClass)) { continue; } $bNotInDico = false; $bNotImportant = true; $sClassRes = "//\n"; $sClassRes .= "// Class: {$sClass}\n"; $sClassRes .= "//\n"; $sClassRes .= "\n"; $sClassRes .= "Dict::Add('{$sLanguage}', '{$sDesc}', '{$sLocalizedDesc}', array(\n"; $sClassRes .= MakeDictEntry("Class:{$sClass}", MetaModel::GetName_Obsolete($sClass), $sClass, $bNotInDico); $sClassRes .= MakeDictEntry("Class:{$sClass}+", MetaModel::GetClassDescription_Obsolete($sClass), '', $bNotImportant); foreach (MetaModel::ListAttributeDefs($sClass) as $sAttCode => $oAttDef) { if ($sAttCode == 'friendlyname') { continue; } // Skip this attribute if not originaly defined in this class if (MetaModel::GetAttributeOrigin($sClass, $sAttCode) != $sClass) { continue; } $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}", $oAttDef->GetLabel_Obsolete(), $sAttCode, $bNotInDico); $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}+", $oAttDef->GetDescription_Obsolete(), '', $bNotImportant); if ($oAttDef instanceof AttributeEnum) { if (MetaModel::GetStateAttributeCode($sClass) == $sAttCode) { foreach (MetaModel::EnumStates($sClass) as $sStateCode => $aStateData) { if (array_key_exists('label', $aStateData)) { $sValue = $aStateData['label']; } else { $sValue = MetaModel::GetStateLabel($sClass, $sStateCode); } if (array_key_exists('description', $aStateData)) { $sValuePlus = $aStateData['description']; } else { $sValuePlus = MetaModel::GetStateDescription($sClass, $sStateCode); } $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sStateCode}", $sValue, '', $bNotInDico); $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sStateCode}+", $sValuePlus, '', $bNotImportant); } } else { foreach ($oAttDef->GetAllowedValues() as $sKey => $value) { $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sKey}", $value, '', $bNotInDico); $sClassRes .= MakeDictEntry("Class:{$sClass}/Attribute:{$sAttCode}/Value:{$sKey}+", $value, '', $bNotImportant); } } } } foreach (MetaModel::EnumStimuli($sClass) as $sStimulusCode => $oStimulus) { $sClassRes .= MakeDictEntry("Class:{$sClass}/Stimulus:{$sStimulusCode}", $oStimulus->GetLabel_Obsolete(), '', $bNotInDico); $sClassRes .= MakeDictEntry("Class:{$sClass}/Stimulus:{$sStimulusCode}+", $oStimulus->GetDescription_Obsolete(), '', $bNotImportant); } $sClassRes .= "));\n"; $sClassRes .= "\n"; $sRes .= $sClassRes; } } return $sRes; }
/** * Create form to apply a stimulus * @param WebPage $oP The current web page * @param Object $oObj The target object * @param String $sStimulusCode Stimulus that will be applied * @param Array $aEditAtt List of attributes to edit * @return void */ function MakeStimulusForm(WebPage $oP, $oObj, $sStimulusCode, $aEditAtt) { static $bHasStimulusForm = false; $sDialogId = $sStimulusCode . "_dialog"; $sFormId = $sStimulusCode . "_form"; $sCancelButtonLabel = Dict::S('UI:Button:Cancel'); $oP->add('<div id="' . $sDialogId . '" style="display: none;">'); $sClass = get_class($oObj); $oP->add('<form id="' . $sFormId . '" method="post">'); $sTransactionId = utils::GetNewTransactionId(); $oP->add("<input type=\"hidden\" id=\"transaction_id\" name=\"transaction_id\" value=\"{$sTransactionId}\">\n"); $oP->add("<input type=\"hidden\" name=\"class\" value=\"{$sClass}\">"); $oP->add("<input type=\"hidden\" name=\"id\" value=\"" . $oObj->GetKey() . "\">"); $oP->add("<input type=\"hidden\" name=\"operation\" value=\"update_request\">"); $oP->add("<input type=\"hidden\" id=\"stimulus_to_apply\" name=\"apply_stimulus\" value=\"{$sStimulusCode}\">\n"); $aTransitions = $oObj->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli($sClass); if (!isset($aTransitions[$sStimulusCode])) { // Invalid stimulus throw new ApplicationException(Dict::Format('UI:Error:Invalid_Stimulus_On_Object_In_State', $sStimulusCode, $oObj->GetName(), $oObj->GetStateLabel())); } // Compute the attribute flags in the target state $aTransition = $aTransitions[$sStimulusCode]; $sTargetState = $aTransition['target_state']; $aTargetStates = MetaModel::EnumStates($sClass); $aTargetState = $aTargetStates[$sTargetState]; $aExpectedAttributes = $aTargetState['attribute_list']; foreach ($aEditAtt as $sAttCode) { $sValue = $oObj->Get($sAttCode); $sDisplayValue = $oObj->GetEditValue($sAttCode); $aArgs = array('this' => $oObj, 'formPrefix' => ''); $oAttDef = MetaModel::GetAttributeDef($sClass, $sAttCode); $sInputId = 'input_' . $sAttCode; $iFlags = array_key_exists($sAttCode, $aExpectedAttributes) ? $aExpectedAttributes[$sAttCode] : 0; $sHTMLValue = "<span id=\"field_{$sStimulusCode}_{$sInputId}\">" . cmdbAbstractObject::GetFormElementForField($oP, $sClass, $sAttCode, $oAttDef, $sValue, $sDisplayValue, $sInputId, '', $iFlags, $aArgs) . '</span>'; $oP->add('<h1>' . MetaModel::GetLabel($sClass, $sAttCode) . '</h1>'); $oP->add($sHTMLValue); } $oP->add('</form>'); $oP->add('</div>'); if (!$bHasStimulusForm) { $bHasStimulusForm = true; $oP->add_script(<<<EOF function RunStimulusDialog(sStimulusCode, sTitle, sOkButtonLabel) { \tvar sWidth = 'auto'; \tif (sStimulusCode == 'ev_reopen') \t{ \t\t// Avoid having a dialog spanning the complete width of the window \t\t// just because it contains a CaseLog entry \t\tsWidth = '80%'; \t} \t\t\t\t \t\$('#'+sStimulusCode+'_dialog').dialog({ \t\theight: 'auto', \t\twidth: sWidth, \t\tmodal: true, \t\ttitle: sTitle, \t\tbuttons: [ \t\t{ text: sOkButtonLabel, click: function() { \t\t\t\$(this).find('#'+sStimulusCode+'_form').submit(); \t\t} }, \t\t{ text: "{$sCancelButtonLabel}", click: function() { \t\t\t\$(this).dialog( "close" ); \t\t} } \t\t] \t}); \t// Start the validation \tCheckFields(sStimulusCode+'_form', false); \t\$('#'+sStimulusCode+'_form').submit( function() { \t\treturn OnSubmit(sStimulusCode+'_form'); \t}); } EOF ); } }
function test_object_lifecycle() { echo "<h4>Test object lifecycle</h4>"; self::DumpVariable(MetaModel::GetStateAttributeCode("cmdbContact")); self::DumpVariable(MetaModel::EnumStates("cmdbContact")); self::DumpVariable(MetaModel::EnumStimuli("cmdbContact")); foreach (MetaModel::EnumStates("cmdbContact") as $sStateCode => $aStateDef) { echo "<p>Transition from <strong>{$sStateCode}</strong></p>\n"; self::DumpVariable(MetaModel::EnumTransitions("cmdbContact", $sStateCode)); } $oObj = MetaModel::GetObject("cmdbContact", 18); echo "Current state: " . $oObj->GetState() . "... let's go to school..."; self::DumpVariable($oObj->EnumTransitions()); $oObj->ApplyStimulus("toschool"); echo "New state: " . $oObj->GetState() . "... let's get older..."; self::DumpVariable($oObj->EnumTransitions()); $oObj->ApplyStimulus("raise"); echo "New state: " . $oObj->GetState() . "... let's try to go further... (should give an error)"; self::DumpVariable($oObj->EnumTransitions()); $oObj->ApplyStimulus("raise"); // should give an error }
/** * Enumerate services delivered by this class * @param string $sVersion The version (e.g. 1.0) supported by the services * @return RestResult The standardized result structure (at least a message) * @throws Exception in case of internal failure. */ public function ExecOperation($sVersion, $sVerb, $aParams) { $oResult = new RestResultWithObjects(); switch ($sVerb) { case 'core/create': RestUtils::InitTrackingComment($aParams); $sClass = RestUtils::GetClass($aParams, 'class'); $aFields = RestUtils::GetMandatoryParam($aParams, 'fields'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $oObject = RestUtils::MakeObjectFromFields($sClass, $aFields); $oObject->DBInsert(); $oResult->AddObject(0, 'created', $oObject, $aShowFields, $bExtendedOutput); break; case 'core/update': RestUtils::InitTrackingComment($aParams); $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $aFields = RestUtils::GetMandatoryParam($aParams, 'fields'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $oObject = RestUtils::FindObjectFromKey($sClass, $key); RestUtils::UpdateObjectFromFields($oObject, $aFields); $oObject->DBUpdate(); $oResult->AddObject(0, 'updated', $oObject, $aShowFields, $bExtendedOutput); break; case 'core/apply_stimulus': RestUtils::InitTrackingComment($aParams); $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $aFields = RestUtils::GetMandatoryParam($aParams, 'fields'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $sStimulus = RestUtils::GetMandatoryParam($aParams, 'stimulus'); $oObject = RestUtils::FindObjectFromKey($sClass, $key); RestUtils::UpdateObjectFromFields($oObject, $aFields); $aTransitions = $oObject->EnumTransitions(); $aStimuli = MetaModel::EnumStimuli(get_class($oObject)); if (!isset($aTransitions[$sStimulus])) { // Invalid stimulus $oResult->code = RestResult::INTERNAL_ERROR; $oResult->message = "Invalid stimulus: '{$sStimulus}' on the object " . $oObject->GetName() . " in state '" . $oObject->GetState() . "'"; } else { $aTransition = $aTransitions[$sStimulus]; $sTargetState = $aTransition['target_state']; $aStates = MetaModel::EnumStates($sClass); $aTargetStateDef = $aStates[$sTargetState]; $aExpectedAttributes = $aTargetStateDef['attribute_list']; $aMissingMandatory = array(); foreach ($aExpectedAttributes as $sAttCode => $iExpectCode) { if ($iExpectCode & OPT_ATT_MANDATORY && $oObject->Get($sAttCode) == '') { $aMissingMandatory[] = $sAttCode; } } if (count($aMissingMandatory) == 0) { // If all the mandatory fields are already present, just apply the transition silently... if ($oObject->ApplyStimulus($sStimulus)) { $oObject->DBUpdate(); $oResult->AddObject(0, 'updated', $oObject, $aShowFields, $bExtendedOutput); } } else { // Missing mandatory attributes for the transition $oResult->code = RestResult::INTERNAL_ERROR; $oResult->message = 'Missing mandatory attribute(s) for applying the stimulus: ' . implode(', ', $aMissingMandatory) . '.'; } } break; case 'core/get': $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $aShowFields = RestUtils::GetFieldList($sClass, $aParams, 'output_fields'); $bExtendedOutput = RestUtils::GetOptionalParam($aParams, 'output_fields', '*') == '*+'; $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); while ($oObject = $oObjectSet->Fetch()) { $oResult->AddObject(0, '', $oObject, $aShowFields, $bExtendedOutput); } $oResult->message = "Found: " . $oObjectSet->Count(); break; case 'core/delete': $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $bSimulate = RestUtils::GetOptionalParam($aParams, 'simulate', false); $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); $aObjects = $oObjectSet->ToArray(); $this->DeleteObjects($oResult, $aObjects, $bSimulate); break; case 'core/get_related': $oResult = new RestResultWithRelations(); $sClass = RestUtils::GetClass($aParams, 'class'); $key = RestUtils::GetMandatoryParam($aParams, 'key'); $sRelation = RestUtils::GetMandatoryParam($aParams, 'relation'); $iMaxRecursionDepth = RestUtils::GetOptionalParam($aParams, 'depth', 20); $oObjectSet = RestUtils::GetObjectSetFromKey($sClass, $key); $aIndexByClass = array(); while ($oObject = $oObjectSet->Fetch()) { $aRelated = array(); $aGraph = array(); $aIndexByClass[get_class($oObject)][$oObject->GetKey()] = null; $oResult->AddObject(0, '', $oObject); $this->GetRelatedObjects($oObject, $sRelation, $iMaxRecursionDepth, $aRelated, $aGraph); foreach ($aRelated as $sClass => $aObjects) { foreach ($aObjects as $oRelatedObj) { $aIndexByClass[get_class($oRelatedObj)][$oRelatedObj->GetKey()] = null; $oResult->AddObject(0, '', $oRelatedObj); } } foreach ($aGraph as $sSrcKey => $aDestinations) { foreach ($aDestinations as $sDestKey) { $oResult->AddRelation($sSrcKey, $sDestKey); } } } if (count($aIndexByClass) > 0) { $aStats = array(); foreach ($aIndexByClass as $sClass => $aIds) { $aStats[] = $sClass . '= ' . count($aIds); } $oResult->message = "Scope: " . $oObjectSet->Count() . "; Related objects: " . implode(', ', $aStats); } else { $oResult->message = "Nothing found"; } break; case 'core/check_credentials': $oResult = new RestResult(); $sUser = RestUtils::GetMandatoryParam($aParams, 'user'); $sPassword = RestUtils::GetMandatoryParam($aParams, 'password'); if (UserRights::CheckCredentials($sUser, $sPassword) !== true) { $oResult->authorized = false; } else { $oResult->authorized = true; } break; default: // unknown operation: handled at a higher level } return $oResult; }