/**
  * Performs a workflow transition on a document, changing it from
  * one workflow state to another, with potential side effects (user
  * scripts, and so forth).
  *
  * This function currently assumes that the user in question is
  * allowed to perform the transition and that all the guard
  * functionality on the transition has passed.
  */
 function performTransitionOnDocument($oTransition, $oDocument, $oUser, $sComments)
 {
     $oWorkflow =& KTWorkflow::getByDocument($oDocument);
     if (empty($oWorkflow)) {
         return PEAR::raiseError(_kt("Document has no workflow"));
     }
     if (PEAR::isError($oWorkflow)) {
         return $oWorkflow;
     }
     $oSourceState =& KTWorkflowUtil::getWorkflowStateForDocument($oDocument);
     // walk the action triggers.
     $aActionTriggers = KTWorkflowUtil::getActionTriggersForTransition($oTransition);
     if (PEAR::isError($aActionTriggers)) {
         return $aActionTriggers;
         // error out?
     }
     foreach ($aActionTriggers as $oTrigger) {
         $res = $oTrigger->precheckTransition($oDocument, $oUser);
         if (PEAR::isError($res)) {
             return $res;
         }
     }
     $iPreviousMetadataVersion = $oDocument->getMetadataVersionId();
     $oDocument->startNewMetadataVersion($oUser);
     KTDocumentUtil::copyMetadata($oDocument, $iPreviousMetadataVersion);
     $iStateId = $oTransition->getTargetStateId();
     $oDocument->setWorkflowStateId($iStateId);
     $res = $oDocument->update();
     if (PEAR::isError($res)) {
         return $res;
     }
     $oTargetState =& KTWorkflowState::get($iStateId);
     $sSourceState = $oSourceState->getName();
     $sTargetState = $oTargetState->getName();
     // create the document transaction record
     $sTransactionComments = sprintf(_kt("Workflow state changed from %s to %s"), $sSourceState, $sTargetState);
     if ($sComments) {
         $sTransactionComments .= _kt("; Reason given was: ") . $sComments;
     }
     $oDocumentTransaction = new DocumentTransaction($oDocument, $sTransactionComments, 'ktcore.transactions.workflow_state_transition');
     $oDocumentTransaction->create();
     // walk the action triggers.
     foreach ($aActionTriggers as $oTrigger) {
         $res = $oTrigger->performTransition($oDocument, $oUser);
         if (PEAR::isError($res)) {
             return $res;
         }
     }
     KTPermissionUtil::updatePermissionLookup($oDocument);
     KTWorkflowUtil::informUsersForState($oTargetState, KTWorkflowUtil::getInformedForState($oTargetState), $oDocument, $oUser, $sComments);
     return true;
 }