/** * 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; }
public function AddLogEntryFromJSON($oJson, $bCheckUserId = true) { $sText = isset($oJson->message) ? $oJson->message : ''; if (isset($oJson->user_id)) { if (!UserRights::IsAdministrator()) { throw new Exception("Only administrators can set the user id", RestResult::UNAUTHORIZED); } if ($bCheckUserId && $oJson->user_id != 0) { try { $oUser = RestUtils::FindObjectFromKey('User', $oJson->user_id); } catch (Exception $e) { throw new Exception('user_id: ' . $e->getMessage(), $e->getCode()); } $iUserId = $oUser->GetKey(); $sOnBehalfOf = $oUser->GetFriendlyName(); } else { $iUserId = $oJson->user_id; $sOnBehalfOf = $oJson->user_login; } } else { $iUserId = UserRights::GetUserId(); $sOnBehalfOf = UserRights::GetUserFriendlyName(); } if (isset($oJson->date)) { $oDate = new DateTime($oJson->date); $iDate = (int) $oDate->format('U'); } else { $iDate = time(); } $sDate = date(Dict::S('UI:CaseLog:DateFormat'), $iDate); $sSeparator = sprintf(CASELOG_SEPARATOR, $sDate, $sOnBehalfOf, $iUserId); $iSepLength = strlen($sSeparator); $iTextlength = strlen($sText); $this->m_sLog = $sSeparator . $sText . $this->m_sLog; // Latest entry printed first $this->m_aIndex[] = array('user_name' => $sOnBehalfOf, 'user_id' => $iUserId, 'date' => $iDate, 'text_length' => $iTextlength, 'separator_length' => $iSepLength); $this->m_bModified = true; }
/** * 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; }