/** * * @param PMSERequest $request * @return \PMSERequest */ public function validateRequest(PMSERequest $request) { $this->logger->info("Validate Request " . get_class($this)); $this->logger->debug(array("Request data:", $request)); $request->validate(); return $request; }
/** * * @param type $element * @param type $createThread * @param type $bean * @param type $externalAction * @param type $args * @return type */ public function executeRequest($args = array(), $createThread = false, $bean = null, $externalAction = '') { $this->logger->info('Processing a direct request.'); $this->logger->debug('Direct request params: ' . print_r($args)); $this->request->setCreateThread($createThread); $this->request->setExternalAction($externalAction); $this->request->setBean($bean); $this->request->setArguments($args); $preProcessor = $this->preProcessor->getInstance(); $response = $preProcessor->processRequest($this->request); return $response; }
/** * Validates that if a second request from the same event and bean record * is received, the second request should be invalidated and thus ignored. * @param PMSERequest $request * @return \PMSERequest */ public function validateRequest(PMSERequest $request) { $this->logger->info("Validate Request " . get_class($this)); $this->logger->debug(array("Request data:", $request)); $args = $request->getArguments(); $flowId = isset($args['idFlow']) ? $args['idFlow'] : (isset($args['flow_id']) ? $args['flow_id'] : '0'); if (!isset($_SESSION['locked_flows']) || !in_array($flowId, $_SESSION['locked_flows'])) { $request->validate(); } else { $request->invalidate(); } return $request; }
/** * * @param PMSEObservable $subject */ public function update($subject) { if (method_exists($subject, 'getEventDefinition')) { $this->logger->debug("Trigger update of a Related Relationship for a Event Definition update"); $event = $subject->getEvent(); $eventData = $event->fetched_row; $eventDefinition = $subject->getEventDefinition(); $eventDefinitionData = $eventDefinition->fetched_row; $processDefinition = $subject->getProcessDefinition(); $processDefinitionData = $processDefinition->fetched_row ? $processDefinition->fetched_row : array(); $completeData = $eventData + $eventDefinitionData + $processDefinitionData; $this->relatedDependency->processRelatedDependencies($completeData); } }
/** * * @param PMSEObservable $subject * @return type */ public function update($subject) { if (method_exists($subject, 'getProcessDefinition')) { $this->logger->debug("Trigger update of a Related Relationship for a Process Definitions update"); $processDefinition = $subject->getProcessDefinition(); $processDefinitionData = $processDefinition->fetched_row; $fields = array('id', 'rel_element_type'); $relatedDependency = $this->getRelatedDependencyBean(); $this->sugarQuery->select($fields); $this->sugarQuery->from($relatedDependency); $this->sugarQuery->where()->queryAnd()->addRaw("pro_id='{$processDefinitionData['id']}' AND prj_id='{$processDefinitionData['prj_id']}' AND deleted=0"); $result = $this->sugarQuery->compileSql(); $this->logger->debug("Retrieve dependencies query: {$result}"); $rows = $this->sugarQuery->execute(); foreach ($rows as $row) { $bean = $this->getRelatedDependencyBean($row['id']); $bean->pro_status = $processDefinitionData['pro_status']; $bean->pro_locked_variables = $processDefinitionData['pro_locked_variables']; $bean->pro_terminate_variables = $processDefinitionData['pro_terminate_variables']; if ($bean->pro_module !== $processDefinitionData['pro_module'] && $row['rel_element_type'] == 'TERMINATE') { $bean->deleted = true; } $bean->save(); } $this->processRelatedDependencies($processDefinitionData); $depNumber = count($rows); $this->logger->debug("Updating {$depNumber} dependencies"); } return $result; }
/** * * @param PMSERequest $request * @return type */ public function validateRequest(PMSERequest $request) { $this->logger->info("Start validation process."); $this->logger->debug(array("Request Data to be validated: ", $request)); // A default request is always valid, if fails to validate in any validator // the status is set to invalid and no further validation is required if (!isset($this->validators[$request->getType()])) { $this->logger->info("Invalid Request"); return false; } foreach ($this->validators[$request->getType()] as $validatorName => $validatorLevel) { if ($validatorLevel != PMSEValidationLevel::NoValidation) { $validator = $this->retrieveValidator($validatorName, $validatorLevel); $request = $validator->validateRequest($request); if (!$request->isValid()) { $this->logger->info(get_class($validator) . " validator invalidated request."); return $request; } else { $this->logger->info(get_class($validator) . " validator validated request."); } } } $this->logger->info("Request validated successfully"); $request->setStatus('PROCESSED'); return $request; }
/** * * @param type $bean * @param type $flowData * @param type $externalAction * @return array */ public function validateParamsRelated($bean, $flowData) { $paramsRelated = array(); if ($bean->parent_type == $flowData['rel_process_module']) { $paramsRelated = array('replace_fields' => array($flowData['rel_element_relationship'] => $flowData['rel_element_module'])); } $this->logger->debug("Parameters related returned :" . print_r($paramsRelated, true)); return $paramsRelated; }
/** * That method creates all dependencies related to this event and save them * @param array resultArray */ public function createRelatedDependencies($resultArray) { foreach ($resultArray as $object) { $relatedDependency = $this->getBean('pmse_BpmRelatedDependency'); foreach ($object as $attrib => $value) { $relatedDependency->{$attrib} = $value; } $relatedDependency->new_with_id = false; $relatedDependency->save(); } $this->logger->debug("Creating " . count($resultArray) . " Related Dependencies."); }
/** * * @param type $data * @return type */ public function getFlowsByCasId($casId) { $flow = $this->retrieveBean('pmse_BpmFlow'); $q = $this->retrieveSugarQuery(); $fields = array('id', 'deleted', 'assigned_user_id', 'cas_id', 'cas_index', 'pro_id', 'pcas_previous', 'cas_reassign_level', 'bpmn_id', 'bpmn_type', 'cas_user_id', 'cas_thread', 'cas_flow_status', 'cas_sugar_module', 'cas_sugar_object_id', 'cas_sugar_action', 'cas_adhoc_type', 'cas_task_start_date', 'cas_delegate_date', 'cas_start_date', 'cas_finish_date', 'cas_due_date', 'cas_queue_duration', 'cas_duration', 'cas_delay_duration', 'cas_started', 'cas_finished', 'cas_delayed'); $q->select($fields); $q->from($flow); $q->where()->queryAnd()->addRaw("pmse_bpm_flow.cas_id={$casId} AND pmse_bpm_flow.cas_flow_status='ERROR'"); $query = $q->compileSql(); $start = microtime(true); $result = $q->execute(); $time = (microtime(true) - $start) * 1000; $this->logger->debug('Query in order to retrieve all valid start and receive message events: ' . $query . ' \\n in ' . $time . ' milliseconds'); return $result; }
/** * * @param type $bean * @param type $flowData * @param type $request * @return array */ public function validateParamsRelated($bean, $flowData, $request) { $paramsRelated = array(); if ($request->getExternalAction() == 'EVALUATE_RELATED_MODULE') { if ($this->hasValidRelationship($bean, $flowData)) { $paramsRelated = array('replace_fields' => array($flowData['rel_element_relationship'] => $flowData['rel_element_module'])); } else { $request->invalidate(); } } if ($request->getExternalAction() == 'EVALUATE_MAIN_MODULE') { if ($bean->module_name != $flowData['cas_sugar_module'] || $bean->id != $flowData['cas_sugar_object_id']) { $request->invalidate(); } } $this->logger->debug("Parameters related returned :" . print_r($paramsRelated, true)); return $paramsRelated; }
/** * * @global type $db * @param type $bean * @param type $event * @param type $arguments * @param type $startEvents * @param type $isNewRecord */ public function runStartEventBeforeSave($bean, $event, $arguments, $startEvents, $isNewRecord = true) { $this->logger->info("Executing Before save for bean module {$bean->module_name}"); $record['id'] = $bean->id; $record['module_name'] = $bean->module_name; $record['row'] = $bean->fetched_row; if (!$isNewRecord) { $queryDupli = "select * from pmse_bpm_flow where " . "cas_sugar_object_id = '" . $record['id'] . "' " . "and cas_sugar_module = '" . $record['module_name'] . "' " . "and cas_index = 1 "; $resultDupli = $this->dbHandler->Query($queryDupli); $rowDupli = $this->dbHandler->fetchByAssoc($resultDupli); if (is_array($rowDupli)) { $cas_id = $rowDupli['cas_id']; $cas_index = $rowDupli['cas_index']; $pro_id = $rowDupli['pro_id']; $this->logger->debug("[{$cas_id}][{$cas_index}] update in progress"); //$this->bpmLog('DEBUG', ); $pro_locked_variables = array(); $pro_terminate_variables = array(); //iterate over all rows in cas_flow, probably the same record has many open processes while (is_array($rowDupli)) { $queryProcess = "select * from pmse_bpm_process_definition where id = '{$pro_id}' and pro_module = '" . $record['module_name'] . "' "; $resultProcess = $this->dbHandler->Query($queryProcess); $rowProcess = $this->dbHandler->fetchByAssoc($resultProcess); if (trim($rowProcess['pro_locked_variables']) != '') { $array1 = unserialize(trim(htmlspecialchars_decode($rowProcess['pro_locked_variables']))); $pro_locked_variables = array_merge($pro_locked_variables, $array1); } $rowDupli = $this->dbHandler->fetchByAssoc($resultDupli); } $redirect = 'none'; //possible values are 'none', 'partial', 'halt' foreach ($pro_locked_variables as $field) { if ((isset($bean->{$field}) || isset($fetched_row[$field])) && $bean->{$field} != $fetched_row[$field]) { $redirect = 'partial'; $bean->{$field} = $fetched_row[$field]; $this->logger->debug("[{$cas_id}][{$cas_index}] locked field '{$field}' has value '{$bean->{$field}}'"); } } } //there is a case for this record } }
/** * * @param type $flowData * @param type $createThread * @param type $bean * @param type $externalAction * @param type $arguments * @return boolean * @codeCoverageIgnore */ public function runEngine($flowData, $createThread = false, $bean = null, $externalAction = '', $arguments = array()) { // Load the bean if the request comes from a RESUME_EXECUTION related origin // like for example: a timer event execution. if (is_null($bean)) { $bean = BeanFactory::retrieveBean($flowData['cas_sugar_module'], $flowData['cas_sugar_object_id']); } // Validating unreferenced elements when cron jobs are executed, after MACAROON-518 shouldn't have // unreferenced elements. This will validate previous records created before this fix. if ($externalAction == 'WAKE_UP') { $elementBean = BeanFactory::getBean('pmse_BpmnEvent', $flowData['bpmn_id']); if (!isset($elementBean->id)) { // Setting active flow to deleted $fd = BeanFactory::getBean('pmse_BpmFlow', $flowData['id']); $fd->cas_flow_status = 'DELETED'; $fd->save(); // Updating process to error $cf = new PMSECaseFlowHandler(); $cf->changeCaseStatus($flowData['cas_id'], 'TERMINATED'); // Exiting without errors return true; } } $preparedData = $this->caseFlowHandler->prepareFlowData($flowData, $createThread); $this->logger->debug("Begin process Element {$flowData['bpmn_type']}"); try { $executionData = $this->processElement($preparedData, $bean, $externalAction, $arguments); if (isset($executionData['process_bean']) && !empty($executionData['process_bean'])) { $bean = $executionData['process_bean']; } $this->validateFailSafes($flowData, $executionData); $routeData = $this->flowRouter->routeFlow($executionData, $flowData, $createThread); } catch (PMSEElementException $e) { $this->logger->warning($e->getMessage()); $element = $e->getElement(); $flow = $e->getFlowData(); $state = empty($flow['id']) ? 'CREATE' : 'UPDATE'; $executionData = $element->prepareResponse($flow, 'ERROR', $state); // If the status is put into error then the Inbox record should be updated as well $this->caseFlowHandler->changeCaseStatus($executionData['flow_data']['cas_id'], 'ERROR'); $routeData = $this->flowRouter->routeFlow($executionData, $flowData, $createThread); } catch (Exception $e) { $this->logger->warning($e->getMessage()); $element = $this->retrievePMSEElement(''); $status = $e->getCode() == 0 ? 'QUEUE' : 'ERROR'; $preparedData['cas_flow_status'] = $status; $executionData = $element->prepareResponse($preparedData, $status, 'CREATE'); // If the status is put into error then the Inbox record should be updated as well if ($status == 'ERROR') { $this->caseFlowHandler->changeCaseStatus($executionData['flow_data']['cas_id'], 'ERROR'); } $routeData = $this->flowRouter->routeFlow($executionData, $flowData, $createThread); } if ($this->caseFlowHandler->numberOfCasesByStatus($flowData, 'ERROR') <= 0 && $externalAction == 'RESUME_EXECUTION') { $this->caseFlowHandler->changeCaseStatus($flowData['cas_id'], 'IN PROGRESS'); } if (!empty($routeData['next_elements'])) { $createThread = sizeof($routeData['next_elements']) > 1; if ($createThread) { $startTime = ($this->maxExecutionTimeout - $this->executionTime) / sizeof($routeData['next_elements']); } foreach ($routeData['next_elements'] as $elementData) { //reset execution time if the derivation is in parallel $this->executionTime = $createThread ? $startTime : $this->executionTime; $this->runEngine($elementData, $createThread, $bean); } } else { // Quick fix to the 0 output printed by some element, // TODO: Don't remove until the fix to the element is commited ob_get_clean(); return true; } return true; }