Exemplo n.º 1
0
 function do_performquicktransition()
 {
     $oForm = $this->form_quicktransition();
     $res = $oForm->validate();
     if (!empty($res['errors'])) {
         return $oForm->handleError();
     }
     $this->startTransaction();
     $data = $res['results'];
     $oTransition = KTWorkflowTransition::get($_REQUEST['fTransitionId']);
     $res = KTWorkflowUtil::performTransitionOnDocument($oTransition, $this->oDocument, $this->oUser, $data['reason']);
     if (!Permission::userHasDocumentReadPermission($this->oDocument)) {
         $this->commitTransaction();
         $_SESSION['KTInfoMessage'][] = _kt('Transition performed') . '. ' . _kt('You no longer have permission to view this document');
         controllerRedirect('browse', sprintf('fFolderId=%d', $this->oDocument->getFolderId()));
     } else {
         $this->commitTransaction();
         $_SESSION['KTInfoMessage'][] = _kt('Transition performed');
         controllerRedirect('viewDocument', sprintf('fDocumentId=%d', $this->oDocument->getId()));
     }
 }
Exemplo n.º 2
0
 function generateWorkflowTriggers()
 {
     require_once KT_LIB_DIR . '/workflow/workflowutil.inc.php';
     // get all the transitions, and add a trigger to the util with the appropriate settings.
     $KTWFTriggerReg =& KTWorkflowTriggerRegistry::getSingleton();
     $aTransitions = KTWorkflowTransition::getList();
     foreach ($aTransitions as $oTransition) {
         // guard perm
         $iGuardPerm = $oTransition->getGuardPermissionId();
         if (!is_null($iGuardPerm)) {
             $sNamespace = 'ktcore.workflowtriggers.permissionguard';
             $oPerm = KTPermission::get($iGuardPerm);
             $oTrigger = $KTWFTriggerReg->getWorkflowTrigger($sNamespace);
             $oTriggerConfig = KTWorkflowTriggerInstance::createFromArray(array('transitionid' => KTUtil::getId($oTransition), 'namespace' => $sNamespace, 'config' => array('perms' => array($oPerm->getName()))));
         }
         // guard group
         $iGuardGroup = $oTransition->getGuardGroupId();
         if (!is_null($iGuardGroup)) {
             $sNamespace = 'ktcore.workflowtriggers.groupguard';
             $oTrigger = $KTWFTriggerReg->getWorkflowTrigger($sNamespace);
             $oTriggerConfig = KTWorkflowTriggerInstance::createFromArray(array('transitionid' => KTUtil::getId($oTransition), 'namespace' => $sNamespace, 'config' => array('group_id' => $iGuardGroup)));
         }
         // guard role
         $iGuardRole = $oTransition->getGuardRoleId();
         if (!is_null($iGuardRole)) {
             $sNamespace = 'ktcore.workflowtriggers.roleguard';
             $oTrigger = $KTWFTriggerReg->getWorkflowTrigger($sNamespace);
             $oTriggerConfig = KTWorkflowTriggerInstance::createFromArray(array('transitionid' => KTUtil::getId($oTransition), 'namespace' => $sNamespace, 'config' => array('role_id' => $iGuardRole)));
         }
         // guard condition
         $iGuardCondition = $oTransition->getGuardConditionId();
         if (!is_null($iGuardCondition)) {
             $sNamespace = 'ktcore.workflowtriggers.conditionguard';
             $oTrigger = $KTWFTriggerReg->getWorkflowTrigger($sNamespace);
             $oTriggerConfig = KTWorkflowTriggerInstance::createFromArray(array('transitionid' => KTUtil::getId($oTransition), 'namespace' => $sNamespace, 'config' => array('condition_id' => $iGuardCondition)));
         }
     }
 }
Exemplo n.º 3
0
 function finalise()
 {
     $fWizardKey = KTUtil::arrayGet($_REQUEST, 'fWizardKey');
     if (!empty($fWizardKey)) {
         $this->errorRedirectToMain(_kt("Could not create workflow."));
         exit;
     }
     $wiz_data = $_SESSION['_wiz_data'][$fWizardKey];
     // gather all our data.  we're sure this is all good and healthy.
     $states = $wiz_data['states'];
     $transitions = $wiz_data['transitions'];
     $from = $wiz_data['from'];
     $to = $wiz_data['to'];
     $initial_state = $wiz_data['initial_state'];
     $workflow_name = $wiz_data['workflow_name'];
     $this->startTransaction();
     // create the initial workflow
     $oWorkflow = KTWorkflow::createFromArray(array('name' => $workflow_name, 'humanname' => $workflow_name, 'enabled' => true));
     if (PEAR::isError($oWorkflow)) {
         $this->errorRedirectToMain(sprintf(_kt("Failed to create workflow: %s"), $oWorkflow->getMessage()));
     }
     $iWorkflowId = $oWorkflow->getId();
     // create the states.
     $aStates = array();
     foreach ($states as $state_name) {
         $oState = KTWorkflowState::createFromArray(array('workflowid' => $iWorkflowId, 'name' => $state_name, 'humanname' => $state_name));
         if (PEAR::isError($oState)) {
             $this->errorRedirectToMain(sprintf(_kt("Failed to create state: %s"), $oState->getMessage()));
         }
         $aStates[$state_name] = $oState;
     }
     // update the initial state on workflow
     $oInitialState = $aStates[$initial_state];
     $oWorkflow->setStartStateId($oInitialState->getId());
     $res = $oWorkflow->update();
     if (PEAR::isError($res)) {
         $this->errorRedirectToMain(sprintf(_kt("Failed to update workflow: %s"), $res->getMessage()));
     }
     // next, we create and hook up the transitions.
     $aTransitions = array();
     foreach ($transitions as $transition) {
         $dest_name = $to[$transition];
         $oDestState = $aStates[$dest_name];
         $oTransition = KTWorkflowTransition::createFromArray(array("WorkflowId" => $iWorkflowId, "Name" => $transition, "HumanName" => $transition, "TargetStateId" => $oDestState->getId(), "GuardPermissionId" => null, "GuardGroupId" => null, "GuardRoleId" => null, "GuardConditionId" => null));
         if (PEAR::isError($oTransition)) {
             $this->errorRedirectToMain(sprintf(_kt("Failed to create transition: %s"), $oTransition->getMessage()));
         }
         // hook up source states.
         $state_ids = array();
         $sources = (array) $from[$transition];
         foreach ($sources as $state_name) {
             // must exist.
             $oState = $aStates[$state_name];
             $state_ids[] = $oState->getId();
         }
         $res = KTWorkflowAdminUtil::saveTransitionSources($oTransition, $state_ids);
         if (PEAR::isError($res)) {
             $this->errorRedirectToMain(sprintf(_kt("Failed to set transition origins: %s"), $res->getMessage()));
         }
     }
     $this->commitTransaction();
     // finally, we want to redirect the user to the parent dispatcher somehow.
     // FIXME nbm:  how do you recommend we do this?
     $base = $_SERVER['PHP_SELF'];
     $qs = sprintf("action=view&fWorkflowId=%d", $oWorkflow->getId());
     $url = KTUtil::addQueryString($base, $qs);
     $this->addInfoMessage(_kt("Your new workflow has been created.  You may want to configure security and notifications from the menu on the left."));
     redirect($url);
 }
Exemplo n.º 4
0
 /**
  * This performs a transition to a new state of the workflow on the document
  *
  * @author KnowledgeTree Team
  * @access public
  * @param string $transition The transition to perform
  * @param string $reason The reason for transitioning the document to a new state
  * @return void|PEAR_Error Returns nothing on success | a PEAR_Error on failure
  */
 function perform_workflow_transition($transition, $reason)
 {
     $user = $this->can_user_access_object_requiring_permission($this->document, KTAPI_PERMISSION_WORKFLOW);
     if (PEAR::isError($user)) {
         return $user;
     }
     $workflowid = $this->document->getWorkflowId();
     if (empty($workflowid)) {
         return new PEAR_Error(KTAPI_ERROR_WORKFLOW_NOT_IN_PROGRESS);
     }
     $transition =& KTWorkflowTransition::getByName($transition);
     if (is_null($transition) || PEAR::isError($transition)) {
         return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $transition);
     }
     DBUtil::startTransaction();
     $result = KTWorkflowUtil::performTransitionOnDocument($transition, $this->document, $user, $reason);
     if (is_null($result) || PEAR::isError($result)) {
         DBUtil::rollback();
         return new KTAPI_Error(KTAPI_ERROR_WORKFLOW_INVALID, $transition);
     }
     DBUtil::commit();
 }
Exemplo n.º 5
0
 /**
  * Gets which workflow transitions are available to be chosen from
  * this workflow state.
  *
  * Workflow transitions have only destination workflow states, and
  * it is up to the workflow state to decide which workflow
  * transitions it wants to allow to leave its state.
  *
  * This function optionally will return the database id numbers of
  * the workflow transitions using the 'ids' option.
  */
 function getTransitionsFrom($oState, $aOptions = null)
 {
     $bIds = KTUtil::arrayGet($aOptions, 'ids');
     $sTable = KTUtil::getTableName('workflow_state_transitions');
     $aQuery = array("SELECT transition_id FROM {$sTable} WHERE state_id = ?", array($oState->getId()));
     $aTransitionIds = DBUtil::getResultArrayKey($aQuery, 'transition_id');
     if (PEAR::isError($aTransitionIds)) {
         return $aTransitionIds;
     }
     if ($bIds) {
         return $aTransitionIds;
     }
     $aRet = array();
     foreach ($aTransitionIds as $iId) {
         $aRet[] =& KTWorkflowTransition::get($iId);
     }
     return $aRet;
 }
Exemplo n.º 6
0
 function get_graph($oWorkflow)
 {
     $fontsize = 11.0;
     $fontname = "Times-Roman";
     $opts = array('fontsize' => $fontsize, 'fontname' => $fontname);
     $graph = new Image_GraphViz(true, $opts);
     $graph->dotCommand = $this->dotCommand;
     // we need all states & transitions
     // FIXME do we want guards?
     // we want to enable link-editing, and indicate that transitions "converge"
     // so we use a temporary "node" for transitions
     // we also use a "fake" URL which we catch later
     // so we can give good "alt" tags.
     $states = KTWorkflowState::getByWorkflow($oWorkflow);
     $transitions = KTWorkflowTransition::getByWorkflow($oWorkflow);
     $this->state_names = array();
     $this->transition_names = array();
     $state_opts = array('shape' => 'box', 'fontsize' => $fontsize, 'fontname' => $fontname);
     $transition_opts = array('shape' => 'box', 'color' => '#ffffff', 'fontsize' => $fontsize, 'fontname' => $fontname);
     $finaltransition_opts = array('color' => '#333333');
     $sourcetransition_opts = array('color' => '#999999');
     // to make this a little more useful, we want to cascade our output from
     // start to end states - this will tend to give a better output.
     //
     // to do this, we need to order our nodes in terms of "nearness" to the
     // initial node.
     $processing_nodes = array();
     $sorted_ids = array();
     $availability = array();
     $sources = array();
     $destinations = array();
     $states = KTUtil::keyArray($states);
     $transitions = KTUtil::keyArray($transitions);
     foreach ($transitions as $tid => $oTransition) {
         $sources[$tid] = KTWorkflowAdminUtil::getSourceStates($oTransition, array('ids' => true));
         $destinations[$tid] = $oTransition->getTargetStateId();
         foreach ($sources[$tid] as $sourcestateid) {
             $av = (array) KTUtil::arrayGet($availability, $sourcestateid, array());
             $av[] = $tid;
             $availability[$sourcestateid] = $av;
         }
     }
     //var_dump($sources); exit(0);
     //var_dump($availability); exit(0);
     $processing = array($oWorkflow->getStartStateId());
     while (!empty($processing)) {
         $active = array_shift($processing);
         if (!$processing_nodes[$active]) {
             // mark that we've seen this node
             $processing_nodes[$active] = true;
             $sorted[] = $active;
             // now add all reachable nodes to the *end* of the queue.
             foreach ((array) $availability[$active] as $tid) {
                 $next = $destinations[$tid];
                 if (!$processing_nodes[$next]) {
                     $processing[] = $next;
                 }
             }
         }
         //var_dump($processing);
     }
     //var_dump($sorted); exit(0);
     foreach ($sorted as $sid) {
         $oState = $states[$sid];
         $this->state_names[$oState->getId()] = $oState->getHumanName();
         $local_opts = array('URL' => sprintf("s%d", $oState->getId()), 'label' => $oState->getHumanName(), 'color' => '#666666');
         if ($oState->getId() == $oWorkflow->getStartStateId()) {
             $local_opts['color'] = '#000000';
             $local_opts['style'] = 'filled';
             $local_opts['fillcolor'] = '#cccccc';
         }
         $graph->addNode(sprintf('state%d', $oState->getId()), KTUtil::meldOptions($state_opts, $local_opts));
     }
     foreach ($transitions as $tid => $oTransition) {
         $name = sprintf('transition%d', $tid);
         $this->transition_names[$oTransition->getId()] = $oTransition->getHumanName();
         // we "cheat" and use
         $graph->addNode($name, KTUtil::meldOptions($transition_opts, array('URL' => sprintf("t%d", $tid), 'label' => $oTransition->getHumanName())));
         $dest = sprintf("state%d", $oTransition->getTargetStateId());
         $graph->addEdge(array($name => $dest), $finaltransition_opts);
         foreach ($sources[$tid] as $source_id) {
             $source_name = sprintf("state%d", $source_id);
             $graph->addEdge(array($source_name => $name), $sourcetransition_opts);
         }
     }
     // some simple analysis
     $errors = array();
     $info = array();
     $sourceless_transitions = array();
     foreach ($transitions as $tid => $oTransition) {
         if (empty($sources[$tid])) {
             $sourceless_transitions[] = $oTransition->getHumanName();
         }
     }
     if (!empty($sourceless_transitions)) {
         $errors[] = sprintf(_kt("Some transitions have no source states: %s"), implode(', ', $sourceless_transitions));
     }
     $unlinked_states = array();
     foreach ($states as $sid => $oState) {
         if (!$processing_nodes[$sid]) {
             // quick sanity check
             $unlinked_states[] = $oState->getHumanName();
         }
     }
     if (!empty($unlinked_states)) {
         $errors[] = sprintf(_kt("Some states cannot be reached from the initial state (<strong>%s</strong>): %s"), $states[$oWorkflow->getStartStateId()]->getHumanName(), implode(', ', $unlinked_states));
     }
     $data = array('graph' => $graph, 'errors' => $errors, 'info' => $info);
     return $data;
 }